jonobr1 / two.js

A renderer agnostic two-dimensional drawing api for the web.
https://two.js.org
MIT License
8.27k stars 454 forks source link

Best way to edit graphics for Two.js? #727

Closed rttll closed 1 week ago

rttll commented 2 months ago

Describe your question

I'm building an indoor mapping system w/ Two.js. It's a refactor of our current map built on Leaflet.js. I need to be able to edit the perimeter of buildings and other features.

Rather than build an ui/editor in Two.js, I want to grab the resulting svg from the browser (via developer tools), edit in a vector editor, and import back into Two.js

Issue is the re-imported svg is not accurate.

Does anyone have a recommendation for vector editor that will keep the exact imported svg path? I'm also open to other solutions for this...

Twojs has been perfect for this project, I just need to solve this last part.

Your code (either pasted here, or a link to a hosted example)

(code just below) Original perimeter, defined as coordinates. Used to build building perimeter w/ Twojs. Originally from cad drawing. Converted to two.js vertices / created two.js Path, works great and accurate.


"coordinates": [
    [-42.5497, 50.1568],
    [-30.3802, 62.173],
    [-21.918376131139716, 49.20360783346553],
    [-25.240068622497233, 45.90563320787479],
    [-22.8815, 43.1813],
   /// ..... plus 60 more lines
]

(code below) Resulting def generated by Twojs. This is all fine and accurate. I pull the entire out and open in illustrator.

<path  d="M -42.5497 50.1568 L -30.3802 62.173 L -21.918377 49.203607 L -25.240069 45.905633 L -22.8815 43.1813 L -19.953586 46.118444 L -17.939908 43.036048 L -20.759863 40.585986 L -17.456354 36.905535 L -15.274081 38.608964 L -4.868249 27.97941 L 10.053109 21.088503 L 2.529336 4.129081 L 31.0446 -7.6303 L 35.4272 -27.4655 L 87.9019 -27.4714 L 92.0245 -8.1294 L 119.7615 2.0651 L 113.4351 19.3758 L 128.696166 27.579284 L 128.9291 27.944091 L 131.148254 26.340881 L 133.208862 29.164428 L 131.019958 30.684204 L 133.360229 33.484741 L 135.440368 31.998596 L 137.801391 35.09027 L 135.760013 36.719661 L 149.562061 56.088794 L 154.13961 52.849499 L 157.667203 57.827213 L 152.979341 61.065472 L 164.09621 78.063363 L 140.7202 92.1117 L 138.316542 95.22377 L 129.976 88.7213 L 129.73112 63.754862 L 125.711938 65.095664 L 121.29789 61.002445 L 121.558703 57.390046 L 105.246218 45.567156 L 102.095958 46.74782 L 96.922623 43.650069 L 96.666195 39.885154 L 66.9728 35.5571 L 64.9548 38.3294 L 70.534574 38.338018 L 70.5321 48.2167 L 51.9928 48.2167 L 51.9928 38.2947 L 56.7512 38.3117 L 55.0959 35.0093 L 29.9923 42.5941 L 22.7683 45.5876 L -0.911614 58.2808 L -0.882657 60.758456 L -5.66266 63.644183 L -7.878137 62.257243 L -10.6249 89.5244 L -15.261199 94.194667 L -13.770639 95.649049 L -17.413996 99.256214 L -40.601323 78.874729 L -30.589141 68.380726 L -45.8173 54.3971 L -42.5497 50.1568 Z " >

I then export the svg out of illustrator (code below). Path exported back out from Adobe illustrator (no changes made). The def is different but that's fine, in theory, as long as the shape is equivalent. But it's slightly off (see screenshot)

note: width /height values here don't come from Illustrator. they come from running getBoundingClientRect(true) on the two.js path. So it gets constrainted back to the original dimensions.


 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 241.19 145.47"     height="126.74761459506672"     width="209.93351001953073"     >            <path class="cls-1" d="M3.74,89.03l14,13.8,9.7-14.9-3.8-3.8,2.7-3.1,3.4,3.4,2.3-3.5-3.2-2.8,3.8-4.2,2.5,2,11.9-12.2,17.1-7.9-8.6-19.5,32.7-13.5L93.24.03h60.3l4.7,22.2,31.9,11.7-7.3,19.9,17.5,9.4.3.4,2.5-1.8,2.4,3.2-2.5,1.7,2.7,3.2,2.4-1.7,2.7,3.6-2.3,1.9,15.8,22.2,5.3-3.7,4.1,5.7-5.4,3.7,12.8,19.5-26.8,16.1-2.8,3.6-9.6-7.5-.3-28.7-4.6,1.5-5.1-4.7.3-4.1-18.7-13.6-3.6,1.4-5.9-3.6-.3-4.3-34.1-5-2.3,3.2h6.4v11.3h-21.3v-11.3h5.5l-1.9-3.8-28.8,8.7-8.3,3.4-27.3,14.7v2.8l-5.5,3.3-2.5-1.6-3.2,31.3-5.3,5.4,1.7,1.7-4.2,4.1-26.6-23.4,11.5-12.1L.04,93.83l3.7-4.8h0Z"/> </svg>

This resulting svg from illustrator is placed back in two.js via interpret. I don't manipulate it except height/width is added as mentoned above.

As you can see below it's a bit off. Since this is a mapping project, it needs to be exact.

Screenshots

It's really close but slightly off (black: original. red: from illustrator)

Screen Shot 2024-06-10 at 8 33 19 PM

Environment (please select one):


If applicable:

Additional context Add any other context about the problem here.

jonobr1 commented 2 months ago

Judging by the <path /> comparisons it looks like Adobe Illustrator clamps or rounds the values. Many of the coordinates have only 1 decimal place whereas the Two.js version are clamped at 4 decimal places. This makes me think it's a precision error.

Have you tried scaling up the object to be more or less whole numbers? This way slight variations won't be lost as much between applications.

Nice work!

rttll commented 2 months ago

Yeah that makes sense, Illustrator is rounding it slightly.

I haven't tried scaling. I think we'd lose accuracy though, since the current shape exactly matches the building we're mapping (original points came out of autocad).

More updates:

Tested the import/export process with the boxy-svg editor, and it maintains the exact points, so that is promising. Also looking to Onshape and other cad software instead of svg editors. So instead of importing/interpreting an svg back in , we'll import updated coordinates. Also looking promising...

Thanks for the quick reply!

jonobr1 commented 2 months ago

You don't have to change the shape it's just a conversion when you export / import. So exporting you'd scale by 1000 and then when importing from Illustrator you'd divide again by 1000.

rttll commented 1 week ago

After trying a few CAD apps, I settled on Boxy SVG. The main issue with CAD was a smooth import / export process. Boxy SVG allows direct editing of the svg w/in the same coordinate space with a 1:1 scale to two.js, and doesn't round any path values. It's working great.

Thanks again for your help @jonobr1

jonobr1 commented 1 week ago

Glad it worked out!