{"id":2686,"date":"2016-06-28T21:57:41","date_gmt":"2016-06-28T21:57:41","guid":{"rendered":"http:\/\/louisc.co.uk\/?p=2686"},"modified":"2016-11-05T11:17:47","modified_gmt":"2016-11-05T11:17:47","slug":"placing-text-along-a-path-using-geomerative-and-processing","status":"publish","type":"post","link":"https:\/\/louisc.co.uk\/?p=2686","title":{"rendered":"Placing text along a path using Geomerative and Processing"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>In the last post <span style=\"text-decoration: underline;\"><strong><a href=\"http:\/\/louisc.co.uk\/?p=2657\">here<\/a><\/strong>\u00a0<\/span>we explored<span style=\"text-decoration: underline;\"><strong><a href=\"http:\/\/louisc.co.uk\/?p=2657\"> placing points along an a wave path<\/a><\/strong><\/span> we had created all using the built in functionality of the Geomerative library. This was ultimately to allow text to be placed along the path, which is what today&#8217;s post will cover.<\/p>\n<p>If you have not read the previous posts, you will require a great library for processing named &#8220;Geomerative&#8221; \u00a0(<a href=\"http:\/\/www.ricardmarxer.com\/geomerative\/\" target=\"_blank\">Website<\/a>) by <a href=\"http:\/\/www.ricardmarxer.com\/\" target=\"_blank\">Ricard Marxer<\/a>.\u00a0 I have struggled to find many similar sketches online other than those included in the examples, so i figured I would share my progress with the community which has always given me so much! This post whilst keeping a log for my own future use, I hope may serve as a reference for others\u00a0out there with the same aims as me.<\/p>\n<h2>First &#8211; Get some characters\u00a0in place<\/h2>\n<p>So first up, lets just get some text on the points we established in the last post. This looks like:<\/p>\n<p><a href=\"http:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000697.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-2691 alignnone\" src=\"http:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000697.jpg\" alt=\"Geromerative Text to Path No Rotation\" width=\"800\" height=\"450\" srcset=\"https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000697-200x113.jpg 200w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000697-300x169.jpg 300w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000697-400x225.jpg 400w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000697-600x338.jpg 600w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000697-768x432.jpg 768w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000697.jpg 800w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<p>The code\u00a0to make this:<\/p>\n<div class=\"fusion-fullwidth fullwidth-box hundred-percent-fullwidth non-hundred-percent-height-scrolling\"  style='background-color: rgba(255,255,255,0);background-position: center center;background-repeat: no-repeat;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;'><div class=\"fusion-builder-row fusion-row \"><div  class=\"fusion-layout-column fusion_builder_column fusion_builder_column_1_1  fusion-one-full fusion-column-first fusion-column-last fusion-column-no-min-height 1_1\"  style='margin-top:0px;margin-bottom:0px;'>\n\t\t\t\t\t<div class=\"fusion-column-wrapper\" style=\"background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;\"  data-bg-url=\"\">\n\t\t\t\t\t\t\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nimport geomerative.*;\r\nRShape wave;\r\nRFont font;\r\n\r\nfloat plusminus =0.0;\r\nfloat scale = 3;\r\nString message = &quot;hello bendy world &amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&quot;;\r\nint index = 0;\r\n\r\n\/\/Somwhere to store our curve points\r\nRPoint[] points;\r\n\r\nvoid setup()\r\n{\r\n \/\/ From the examples we must always initialise the library using this command\r\n RG.init(this);\r\n \r\n \/\/Usual Processing Jazz\r\n size(800 ,450);\r\n background(255);\r\n frameRate(25);\r\n \r\n font = new RFont(&quot;Impact Label Reversed.ttf&quot;, 72, RIGHT);\r\n}\r\n\r\nvoid draw(){\r\n \/\/Blank Background each frame\r\n background(255);\r\n \r\n \/\/Create a new RShape each frame\r\n RShape wave = new RShape();\r\n \r\n \/\/At the moment the wave object is empty, so lets add a curve:\r\n wave.addMoveTo(0*scale, 100*scale);\r\n wave.addBezierTo(0*scale, 100*scale, 50*scale, 25*scale, 100*scale, 100*scale);\r\n wave.addBezierTo(100*scale, 100*scale, 150*scale, 175*scale, 200*scale, 100*scale); \r\n \r\n \r\n \/\/Lets draw away from the edges\r\n translate(100,-80);\r\n \r\n \/\/Draw our wave\r\n noFill();\r\n stroke(0);\r\n strokeWeight(60);\r\n strokeCap(PROJECT);\r\n wave.draw();\r\n strokeCap(ROUND);\r\n \r\n \/\/Collect some points along the curve\r\n RG.setPolygonizer(RG.UNIFORMLENGTH);\r\n RG.setPolygonizerLength(35);\r\n points = wave.getPoints(); \r\n \r\n index=0; \/\/Letter index within the string message\r\n \r\n \/\/Loop through and place a letter at each point\r\n for(int i=0; i&amp;amp;lt;points.length-1; i++){ \r\n \/\/Add a dot for the point\r\n stroke(0, 90, 255); \/\/Blue\r\n strokeWeight(5);\r\n point(points[i].x, points[i].y);\r\n \r\n fill(255);\r\n noStroke();\r\n\r\n \/\/Draw the current letter\r\n pushMatrix();\r\n translate(points[i].x, points[i].y);\r\n \/\/This is for centering up the font on the line\r\n translate(5, 20); \r\n font.draw(message.charAt(index));\r\n \r\n popMatrix();\r\n \r\n index++;\r\n }\r\n}\r\n}\r\n<\/pre>\n<p>Now, this is a good first step, but we want our lettering to follow the curves, so next we must calculate the angle of each section of curve to correctly rotate our characters.<\/p>\n<p>We can do this with a simple function calculating the angle between two points. Mine simply looks something like this:<\/p>\n<div class=\"fusion-clearfix\"><\/div>\n\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div><div  class=\"fusion-layout-column fusion_builder_column fusion_builder_column_1_1  fusion-one-full fusion-column-first fusion-column-last fusion-column-no-min-height 1_1\"  style='margin-top:0px;margin-bottom:0px;'>\n\t\t\t\t\t<div class=\"fusion-column-wrapper\" style=\"background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;\"  data-bg-url=\"\">\n\t\t\t\t\t\t\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/Simple function to calculate the angle between two points\r\nfloat getAngle(RPoint p1, RPoint p2){\r\n float deltax = p1.x - p2.x;\r\n float deltay= p1.y - p2.y;\r\n \r\n return atan(deltay\/deltax);\r\n}\r\n<\/pre>\n<p>Now we can rotate the canvas where we were translating with a quick call to this new function:<\/p>\n<div class=\"fusion-clearfix\"><\/div>\n\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div><div  class=\"fusion-layout-column fusion_builder_column fusion_builder_column_1_1  fusion-one-full fusion-column-first fusion-column-last fusion-column-no-min-height 1_1\"  style='margin-top:0px;margin-bottom:0px;'>\n\t\t\t\t\t<div class=\"fusion-column-wrapper\" style=\"background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;\"  data-bg-url=\"\">\n\t\t\t\t\t\t\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n...\r\n pushMatrix();\r\n translate(points[i].x,points[i].y);\r\n rotate(getAngle(points[i], points[i+1]));\r\n translate(5, 20);\r\n font.draw(message.charAt(index));\r\n popMatrix();\r\n...\r\n<\/pre>\n<p>Resulting in: <a href=\"http:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000035.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-2695 alignnone\" src=\"http:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000035.jpg\" alt=\"Geromerative Text to Path - Basic Rotation\" width=\"800\" height=\"450\" srcset=\"https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000035-200x113.jpg 200w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000035-300x169.jpg 300w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000035-400x225.jpg 400w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000035-600x338.jpg 600w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000035-768x432.jpg 768w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000035.jpg 800w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<p>Most definitely a step in the right direction, but we still see this is not perfect, because the text character is being placed on the first point, where as the angle is being calculated between the points. The best solution would be to place the characters in the center of the two points. We can do this with some simple calculation, or better still use the built in features of the Geomerative library! So after some exploring in the Geomerative Documentation I came across the <a href=\"http:\/\/www.ricardmarxer.com\/geomerative\/documentation\/geomerative\/RGeomElem.html#getCenter()\" target=\"_blank\">getCenter()<\/a> function, perfect!<\/p>\n<div class=\"fusion-clearfix\"><\/div>\n\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div><div  class=\"fusion-layout-column fusion_builder_column fusion_builder_column_1_1  fusion-one-full fusion-column-first fusion-column-last fusion-column-no-min-height 1_1\"  style='margin-top:0px;margin-bottom:0px;'>\n\t\t\t\t\t<div class=\"fusion-column-wrapper\" style=\"background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;\"  data-bg-url=\"\">\n\t\t\t\t\t\t\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n stroke(255, 90, 0); \/\/Orange\r\n strokeWeight(10);\r\n RPoint center = new RCommand(points[i], points[i+1]).getCenter();\r\n point(center.x,center.y);\r\n<\/pre>\n<p>Turning off the text, we are not getting:<\/p>\n<div class=\"fusion-clearfix\"><\/div>\n\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div><div  class=\"fusion-layout-column fusion_builder_column fusion_builder_column_1_1  fusion-one-full fusion-column-first fusion-column-last fusion-column-no-min-height 1_1\"  style='margin-top:0px;margin-bottom:0px;'>\n\t\t\t\t\t<div class=\"fusion-column-wrapper\" style=\"background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;\"  data-bg-url=\"\">\n\t\t\t\t\t\t<div id=\"attachment_2698\" style=\"width: 810px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000067.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2698\" class=\"size-full wp-image-2698\" src=\"http:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000067.jpg\" alt=\"Calculated Center Points Marked in Orange\" width=\"800\" height=\"450\" srcset=\"https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000067-200x113.jpg 200w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000067-300x169.jpg 300w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000067-400x225.jpg 400w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000067-600x338.jpg 600w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000067-768x432.jpg 768w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000067.jpg 800w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><p id=\"caption-attachment-2698\" class=\"wp-caption-text\">Calculated Center Points Marked in Orange<\/p><\/div>\n<p>Now we place the characters in these new center points (center.x, center.y) and use the already calculated rotation resulting in:<\/p>\n<p><a href=\"http:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000057.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-2699 alignnone\" src=\"http:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000057.jpg\" alt=\"Geromerative Text to Path\" width=\"800\" height=\"450\" srcset=\"https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000057-200x113.jpg 200w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000057-300x169.jpg 300w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000057-400x225.jpg 400w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000057-600x338.jpg 600w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000057-768x432.jpg 768w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/louisc_co_uk_Geromerative2-000057.jpg 800w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<p>Complete code PDE can be found here:<\/p>\n<p><a href=\"https:\/\/github.com\/louisc\/processing-standalone-sketches\/blob\/master\/Geomerative_Text_Along_Path\/Geomerative_Text_Along_Path.pde\" target=\"_blank\">https:\/\/github.com\/louisc\/processing-standalone-sketches\/blob\/master\/Geomerative_Text_Along_Path\/Geomerative_Text_Along_Path.pde\u00a0<\/a><\/p>\n<p>In Repo:<\/p>\n<p>https:\/\/github.com\/louisc\/processing-standalone-sketches<div class=\"fusion-clearfix\"><\/div>\n\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Introduction In the last post here\u00a0we explored placing points along an a wave path we had created all using the built in functionality of the Geomerative library. This was ultimately to allow text to be placed along the path, which is what today&#8217;s post will cover. If you have not read the previous posts, you will require a great library for processing named &#8220;Geomerative&#8221; \u00a0(Website) by Ricard Marxer.\u00a0 I have struggled to find many similar sketches online [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2690,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[103,108,28,1],"tags":[],"class_list":["post-2686","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kinetic-storyteller","category-programming","category-projects","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2686","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2686"}],"version-history":[{"count":11,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2686\/revisions"}],"predecessor-version":[{"id":2714,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2686\/revisions\/2714"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/media\/2690"}],"wp:attachment":[{"href":"https:\/\/louisc.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2686"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2686"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2686"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}