Haskell-Things / ImplicitCAD

A math-inspired CAD program in haskell. CSG, bevels, and shells; 2D & 3D geometry; 2D gcode generation...
https://implicitcad.org/
GNU Affero General Public License v3.0
1.38k stars 142 forks source link

Issues with polygon primitive #6

Closed cgranade closed 12 years ago

cgranade commented 12 years ago

Using ExtOpenSCAD rendering mode, ImplicitScad seems to produce some very odd results with the polygon primitive. For instance, with latest git clone, using the following code to render a triangle:

scale(100) polygon(points=[[1.0, 0.0], [-0.5, 0.8660254038], [-0.5, -0.8660254038], [1.0, 0.0]]);

produces an empty SVG output:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> 
</svg>

The same output is produced for a square and a hexagon as well. Bizarrely, however, if I increase the numerical precision of the points on a hexagon, I obtain an octagon:

scale(100) polygon(points=[[1.0, 0.0], [0.50000000000000011102230246251565404236316680908203125, 0.8660254037844385965883020617184229195117950439453125], [-0.4999999999999997779553950749686919152736663818359375, 0.86602540378443870761060452423407696187496185302734375], [-1.0, 0.000000000000000122464679914735320717376402945839660462569212467758006379625612680683843791484832763671875], [-0.500000000000000444089209850062616169452667236328125, -0.86602540378443837454369713668711483478546142578125], [0.4999999999999993338661852249060757458209991455078125, -0.8660254037844390406775119117810390889644622802734375], [1.0, -0.00000000000000024492935982947064143475280589167932092513842493551601275925122536136768758296966552734375]]
);

produces:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> 
  <polyline points=" 40.000004,161.65807 7.6293945e-6,115.47005" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 40.0,161.65807 120.0,161.65807" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 120.0,161.65807 160.0,115.47005" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 7.6293945e-6,115.47005 0.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 160.0,115.47005 160.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 40.000004,0.0 0.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 40.0,0.0 120.0,0.0" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 120.0,0.0 160.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
</svg> 

Edited by @colah to fix formatting Thanks for helping me figure this all out!

colah commented 12 years ago

What a horrendous bug! Thanks for reporting this, I'm working on fixing it. The issue seems to lie in the isIn function in Graphics.Implicit.Primitives.Obj2.polygon...

colah commented 12 years ago

OK. I've committed a fix for this. Everything should work fine as of 2ef63528e4f900f84e8994342601425111677783. If you have a chance to verify that everything is working, that would be appreciated. :)

cgranade commented 12 years ago

Sorry I took so long to verify that 2ef6352 works. I tried the same test cases with c8451baa6701aff5b437096b5e7a233f89997707, though, and got identical results to the the commit from earlier in the week. Maybe it's an issue with my computer? I'm running GHC 7.0.2 on a Fedora 15 i686 system, if that helps at all. If not, please let me know what else I can provide to help. Thanks!

colah commented 12 years ago

I just checked again on fcb47005279350ac7146cd572b1e2b983e904195:

scale(100) polygon(points=[[1.0, 0.0], [0.50000000000000011102230246251565404236316680908203125, 0.8660254037844385965883020617184229195117950439453125], [-0.4999999999999997779553950749686919152736663818359375, 0.86602540378443870761060452423407696187496185302734375], [-1.0, 0.000000000000000122464679914735320717376402945839660462569212467758006379625612680683843791484832763671875], [-0.500000000000000444089209850062616169452667236328125, -0.86602540378443837454369713668711483478546142578125], [0.4999999999999993338661852249060757458209991455078125, -0.8660254037844390406775119117810390889644622802734375], [1.0, -0.00000000000000024492935982947064143475280589167932092513842493551601275925122536136768758296966552734375]]
);

Produces:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> 
  <polyline points=" 40.000004,161.65807 7.6293945e-6,115.47005" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 40.0,161.65807 120.0,161.65807" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 120.0,161.65807 160.0,115.47005" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 7.6293945e-6,115.47005 0.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 160.0,115.47005 160.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 40.000004,0.0 0.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 40.0,0.0 120.0,0.0" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 120.0,0.0 160.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
</svg> 

The expected result. I'll do more work replicating your issues later. This will be resolved!

cgranade commented 12 years ago

I just tried the test case on a new computer, cloning fcb4700, then running the following commands to install:

git clone https://github.com/colah/ImplicitCAD.git
cd ImplicitCAD
cabal install hashmap parallel parsec
cabal update && cabal configure && cabal install
cd ~/tmp/implicitcad-tests
~/.cabal/bin/extopenscad hexagon.escad

Doing this produces the following SVG output:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> 
  <polyline points=" 39.99999,161.65807 0.0,115.47005" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 39.99999,161.65807 119.999985,161.65807" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 119.999985,161.65807 159.99998,115.47005" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 0.0,115.47005 0.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 159.99998,115.47005 160.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 39.99999,0.0 0.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 39.99999,0.0 119.999985,0.0" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
  <polyline points=" 119.999985,0.0 160.0,46.18802" style="stroke:rgb(0,0,255);stroke-width:1;fill:none;"/> 
</svg>

Curiously, both this and the output you posted render as octagons for me when opened in an SVG viewer, rather than as a hexagon as I would have expected. I made the test case using a small Python script (I'm not very good with Haskell yet, so it seemed easier to do in a hurry); perhaps it output a wrong list of points in the first place? Anyway, just for completeness, I've quoted the Python script below. Thanks for all your help with this, and I'm sorry to be a pain!

import mpmath as mp
n_dig = 100
mp.dps = n_dig
mp.pretty = True

TWO_PI = 2 * mp.pi

def mk_polygon_points(sides, radius):
    r = mp.mpf(radius)
    theta = TWO_PI / sides
    return [[r * mp.cos(i * theta), r * mp.sin(i * theta)] for i in range(sides+1)]

def list_str(lst):
    return "[{contents}]".format(
            contents=", ".join(lst)
        )

if __name__ == "__main__":
    print list_str(map(lambda pts: 
        "[%s]" % ", ".join(map(lambda pt: mp.nstr(pt, n_dig), pts)), mk_polygon_points(6, 1)))
colah commented 12 years ago

Ack, OK. This is my fault for not paying close enough attention when commenting. I was about to run out the door and just jotted something down, sorry. :(

In any case, I misunderstood your bug right from the beginning of this, though it got me to catch a bug in polygon. Because it's handy for debugging, if you scale something, it renders with the resolution of its original object. If you add $res = 0.05; to the top of your code, it should work better. The strange results you were giving are because you were falling under or right at the edge of the rendering resolution.

By the way, the code you are running is equivalent to circle(1, $fn=6); which is somewhat easier to work with. I'd suggest trying:

circle(100, $fn = 6);

or

$res = 0.05;
scale(100) circle(1, $fn = 6);

Also, it's worth mentioning that the last point you're giving the polygon is redundant, since it is assumed to loop around. :)

Sorry about being so silly! Please replicate this fixing your problems! And thanks for helping get rid of bugs in ImplicitCAD!

colah commented 12 years ago

This seems to fix everything on my end. I have not heard anything suggesting it is not fixed for you. As such, I'm closing this issue.

If you experience this problem again, please feel free to comment here and I'll reopen the issue.