Алгоритм обтекания текста внутри фигуры - PullRequest
23 голосов
/ 15 июня 2010

Я ищу алгоритм для переноса текста в непрямоугольную форму, предпочтительно на основе алгоритма Кнута и Пласса.Самое сложное в том, что строки могут иметь разную высоту из-за разного размера шрифта в тексте.Изображение ниже является примером того, что алгоритм должен быть в состоянии генерировать.

Text shaped like a heart

Ответы [ 3 ]

5 голосов
/ 25 ноября 2014

Редактировать, обновить

Попробуйте

text / html

        gggggggggggggg              gggggggggggggg 
     gggggggggggggggggggg         gggggggggggggggggg
   gggggggggggggggggggggggg     gggggggggggggggggggggg
 ggggggggggggggggggggggggggg   ggggggggggggggggggggggggg
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
 gggggggggggggggggggggggggggggggggggggggggggggggggggggggg
  gggggggggggggggggggggggggggggggggggggggggggggggggggggg
   gggggggggggggggggggggggggggggggggggggggggggggggggggg
     ggggggggggggggggggggggggggggggggggggggggggggggggg
      gggggggggggggggggggggggggggggggggggggggggggggg
        gggggggggggggggggggggggggggggggggggggggggg
           ggggggggggggggggggggggggggggggggggggg
              gggggggggggggggggggggggggggggg
                 gggggggggggggggggggggggg
                    gggggggggggggggggg
                       gggggggggggg
                         gggggggg
                           ggggg
                            ggg
                             g

js

var text =  "Lorem ipsum dolor sit amet," // `string` , `array` 
, i = -1
, elem = document.querySelector("pre");
elem.innerText = elem.innerText.replace(/[^\n|\r|\t|\s+]/g, function() {
                   return text[++i] 
                 });


        Lorem ipsum do              lor sit amet,  
     consectetur adipisci         ng elit. Vivamus b
   landit nisl eu posuere s     uscipit. Etiam at quam
  sed nulla consequat finibu   s et eget ligula. Nam sit
 amet imperdiet eros. Ut a congue nibh. Sed ac arcu non r
isus commodo lobortis et at lorem. Pellentesque pulvinar v
enenatis pellentesque. Praesent sed pulvinar justo. Ut nec
 turpis lectus. Suspendisse porta ipsum orci, nec vestibul
um tellus luctus quis. Morbi eleifend vel nibh sed rutrum.
 Etiam feugiat, nunc et efficitur accumsan, quam magna lac
 inia neque, eu ullamcorper purus turpis eget urna. Etiam
   lacus mi, gravida vel mollis ut, viverra sed ipsum. M
   auris in augue turpis.Nulla facilisi. In tristique t
     ortor sit amet leo cursus, sit amet varius ligula
       sollicitudin. Mauris commodo et sapien id sce
        lerisque. Integer et diam eget arcu bibend
           um ornare a in tortor. Lorem ipsum do
              lor sit amet, consectetur adip
                 iscing elit. Aliquam veh
                    icula diam ac laor
                       eet tincidun
                         t. Integ
                           er se
                            d t
                             e

var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus blandit nisl eu posuere suscipit. Etiam at quam sed nulla consequat finibus et eget ligula. Nam sit amet imperdiet eros. Ut a congue nibh. Sed ac arcu non risus commodo lobortis et at lorem. Pellentesque pulvinar venenatis pellentesque. Praesent sed pulvinar justo. Ut nec turpis lectus. Suspendisse porta ipsum orci, nec vestibulum tellus luctus quis. Morbi eleifend vel nibh sed rutrum. Etiam feugiat, nunc et efficitur accumsan, quam magna lacinia neque, eu ullamcorper purus turpis eget urna. Etiam lacus mi, gravida vel mollis ut, viverra sed ipsum. Mauris in augue turpis."

+ "Nulla facilisi. In tristique tortor sit amet leo cursus, sit amet varius ligula sollicitudin. Mauris commodo et sapien id scelerisque. Integer et diam eget arcu bibendum ornare a in tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vehicula diam ac laoreet tincidunt. Integer sed tellus sit amet lacus bibendum tristique a a nulla. Quisque venenatis suscipit est eget ultricies. Quisque ac orci convallis, interdum enim quis, dictum justo. Phasellus tincidunt nisi vitae justo fringilla, sit amet pellentesque enim dictum. Duis porttitor convallis feugiat. Sed lectus massa, consectetur et vestibulum a, egestas ac eros. Proin mollis ligula tellus, a dignissim eros placerat sed. Donec vel blandit magna. Etiam quis tortor rhoncus, porta ante et, pretium mi."

+ "Vestibulum ut risus convallis, sagittis orci sed, faucibus erat. Aliquam maximus suscipit lectus, vel pellentesque enim dictum nec. Sed et ex id mauris finibus molestie. Aliquam erat volutpat. Etiam nec ultricies est. Aenean vitae mi id neque vulputate suscipit vel vitae ante. Nam sit amet mi diam. Phasellus efficitur faucibus viverra. Proin cursus purus et tortor dictum elementum. Nunc vehicula erat volutpat, rutrum metus bibendum, blandit sem."

+ "Nam eu ante eros. Sed pellentesque accumsan neque, eu vulputate lectus luctus ac. In hac habitasse platea dictumst. Nulla vitae dictum diam. Sed eget mauris in felis luctus luctus. Mauris volutpat lacus in est dignissim, sit amet venenatis ipsum laoreet. Phasellus semper id velit ut tristique. Proin dictum erat at mauris lacinia blandit. Ut scelerisque mi ex, ut pretium elit commodo sit amet. Praesent faucibus turpis tellus, ac vulputate felis aliquet eget. Ut est urna, dignissim nec risus sit amet, eleifend lacinia enim. Donec non massa in purus efficitur placerat. Donec accumsan neque elit, eget vulputate metus finibus quis. Ut interdum sem vel felis imperdiet pretium. Integer erat neque, bibendum id egestas nec, facilisis sed massa."

+ "Curabitur sit amet mattis odio. Mauris mattis turpis eu lectus eleifend, semper ultrices elit malesuada. Mauris fringilla arcu sed sem vehicula vulputate. Donec semper nisl ut urna bibendum, quis eleifend tortor commodo. Pellentesque vehicula est et neque vulputate accumsan. Duis faucibus sodales lacus et suscipit. Pellentesque tortor enim, pulvinar scelerisque pretium non, aliquam sed risus. Vestibulum aliquam dolor ipsum, eget pretium ante fermentum a. Donec semper lectus pulvinar tellus hendrerit sagittis. Nunc blandit sed ligula vel consequat. Etiam sed est quis nulla blandit blandit. Sed in enim pulvinar elit accumsan faucibus sed sodales lorem. Aenean ac efficitur arcu, sed fringilla lectus."

, i = -1;
var elem = document.querySelector("pre");
elem.innerText = elem.innerText.replace(/[^\n|\r|\t|\s+]/g, function() {
                   return text[++i] 
                 });
    
        gggggggggggggg              gggggggggggggg 
     gggggggggggggggggggg         gggggggggggggggggg
   gggggggggggggggggggggggg     gggggggggggggggggggggg
 ggggggggggggggggggggggggggg   ggggggggggggggggggggggggg
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
 gggggggggggggggggggggggggggggggggggggggggggggggggggggggg
  gggggggggggggggggggggggggggggggggggggggggggggggggggggg
   gggggggggggggggggggggggggggggggggggggggggggggggggggg
     ggggggggggggggggggggggggggggggggggggggggggggggggg
      gggggggggggggggggggggggggggggggggggggggggggggg
        gggggggggggggggggggggggggggggggggggggggggg
           ggggggggggggggggggggggggggggggggggggg
              gggggggggggggggggggggggggggggg
                 gggggggggggggggggggggggg
                    gggggggggggggggggg
                       gggggggggggg
                         gggggggg
                           ggggg
                            ggg
                             g
4 голосов
/ 16 июня 2010

Для простого алгоритма, давайте предположим, что вы можете вычислить ограничивающую рамку вокруг каждого слова и что у вас есть изображение с маской формы, которую вы хотите заполнить.

Смещайте верхнюю часть маски изображения до тех пор, пока не найдете строку длиной до первого слова. Посмотрите, можете ли вы расширить его вниз в прямоугольник размером с ограничивающий прямоугольник. Если так, опустите первое слово там. Если нет, продолжайте подметать.

После того, как вы опустите слово, посмотрите, сможете ли вы расширить ограничивающий прямоугольник до ширины (первый прямоугольник + второй прямоугольник + пробел) и высоты max (первый прямоугольник, второй прямоугольник). Если так, опустите второе слово там. Если нет, отцентрируйте первое слово слева направо в пределах ограничительной рамки, которая будет вписываться в маску изображения (слева направо), удалите эту ограничивающую рамку из маски и продолжайте.

Вы можете сделать это немного причудливее, настаивая на том, что линии имеют одинаковую базовую линию, даже если они разбиты по форме (например, линии на верхних частях сердца); Затем вам нужно иметь альтернативное условие «продолжить по этой базовой линии». Но основная идея выше, с маской изображения, которую вы используете, чтобы попытаться поместить прямоугольники внутри, которые удалены, когда вы закончите, сделает эту работу.

(Использовать геометрические операции быстрее, чем основанные на пикселях операции, описанные здесь, но тогда нужно беспокоиться обо всех случаях, чтобы выяснить, как ограничивающий прямоугольник вписывается в произвольный многоугольник, и это немного долго, чтобы объяснить здесь .)

0 голосов
/ 24 ноября 2014

Допустим, каждая буква имеет определенный размер (ширину и высоту, в этом случае мы, вероятно, заботимся только о ширине, потому что все буквы имеют одинаковую высоту).Тогда нам понадобится следующее:

  1. Обернутые объекты каждого слова - чтобы убедиться, что нет фрагментирования слова
  2. заданной ширины каждого слова.
  3. Разделитьмногоугольник на куски, которые являются высотами слова.Таким образом, у вас есть x горизонтальных полос, которые составляют изображение.
  4. Затем найдите ширину внутреннего многоугольника, если вы хотите вписать слова внутри.Это означает, что вы удаляете круглые края сердца.Там, где вертикальная линия может пересекать край сердца на полосе, это место, где вы удаляете круглый край.

Теперь, когда у нас есть размер каждой полосы изображения, скажем, у нас есть это (я использую произвольную единицу для ширины):

[_________] [__________]  <-- 10 width (5 each)
  [__________________] <-- 9 width
    [_____________] <-- 7 width   
       [_______] <-- 5 width
         [___] <-- 3 width
          [_] <-- 2 width

РЕДАКТИРОВАТЬ: Просто понял, как уродливое сердце, мой плохой.

Теперь нам нужен размер каждого слова, и вставить ихпоследовательно.Каждый блок имеет ширину х, а каждый объект слова имеет ширину у.Если y width> x width, мы переходим к следующей строке и проверяем там

considering we already have widths
while(image.hasNextChunk()){
    currentChunk = image.nextChunk();
    if(currentWord.width < currentChunk.width) //insert here and then change currentWord to nextWord
    ...
}

Я думаю, это то, что вы хотите, но я не совсем уверен.Дайте мне знать, если это помогло!:)

...