discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Polyhedron issue.

F
fluidity
Sun, Jan 11, 2015 8:51 AM

Hi all.
I had a polyhedron generation program all running natively in openscad that
I thought was fully working, but after a big investigation I've found that
my renders are faulty to the extent that not only can't I print with
Repetier Host, but if I print in MatterControl it appears to slice and print
fine but after I've used 20grams or so of filament, my RAMPS board just
extrudes but with no more effector movement. Tracing all this back, I have
duplicate facets that I've found using either netfab or meshlab. The meshes
look perfect from the outside.

I can run a delete duplicate facets command which leaves triangles of random
orientation and then manually correct them but this is very tedious, my
latest model has about 2500 triangles. I'd like to avoid generating the
coordinate list externally to Openscad but it's quite a mission already.
Currently, if you imagine a flat underside and top side, with a math
generated mesh stretching between, then I'm calling polyhedron once for each
top/bottom segment pair and once for each level's triangle pair per side per
level. I've seen  http://www.thingiverse.com/thing:8742/#files
http://www.thingiverse.com/thing:8742/#files  which seems to call
polyhedron for each independent facet, but I'm concerned that my render is
possibly confusing vertices between triangles of different polyhedron calls
as being part of new co-incident triangles that I don't actually want.

rawradius=7.5;
levs=3 ;                //min for test
levstep=12;
sides=4;        //min for test
x_tra=16;
step=360/sides;
//translate([0,0,120]){%cube ([120,10,240],center=true);} //profile test

function completed(k)=(((k+1)/(levs+1))); //levels completed fraction of 1
function scle(l) = (sin(completed(l)65+90)); //height scale, terminate
before 90 deg
function offset(a,d)=(((rawradius
x_tra/2)-d5) -scle(d) rawradiusx_tra );
function x(a,d) =( scle(d)
rawradiusx_tra * abs(sin(a/2))+offset(a,d) );
function y(a,d) =(scle(d)rawradius0.6 * sin(a));  //
(sin(a))*1.4

pa=[for(lev=[0:levs+1]) for (a = [0:step:360+step])
[
a == (360+step) ? 0+offset(a,lev) +10: x(a,lev), //x
a == (360+step) ? 0 : y(a,lev), //y
levlevstep //-cos(lev9)levstep14 //
]
];

nxtl=sides+2;

for (level = [0:levs] , a = [0 : 1 : ((360/step)-1)]){side(a,level);}
for (a = [0 : 1 : ((360/step))]){bottom_top(a);}

module bottom_top(a){
polyhedron(points=pa,faces=
[[sides+1,a+1,a], //base triangles
[(levs+1)*nxtl+sides+1,a+(levs+1)*nxtl,a+(levs+1)nxtl+1] //top triangles
]);
}
module side(a,level){
polyhedron(points=pa,faces=
[[a+level
nxtl,a+(level+1)nxtl+1,a+(level+1)nxtl], //side segment
triangles
[a+level
nxtl,a+level
nxtl+1,a+(level+1)*nxtl+1]//side segment triangles
]);
}

I've since found that I can run the "invert negative shells" script on
netfab, apply and then select all, flip triangles and then apply. This gives
me a valid model. However, on a fine mesh, I suspect that the duplicate
triangles are wasting render time and I suspect my implementation is rather
cumbersome with the complete points list defined at each polyhedron call but
only a partial point order definition at each call.

Is polyhedron usage documented more fully anywhere other than on the normal
openscad wiki?
Do I have to define ALL points and point orders for a single completed
polyhedron with one polyhedron command?
At the moment, I'm trying to wrap my head around reformatting the point
order lists as multiple list comprehensions encapsulated in the point order
part of the polyhedron statement but the syntax is messing with my head.

--
View this message in context: http://forum.openscad.org/Polyhedron-issue-tp11003.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Hi all. I had a polyhedron generation program all running natively in openscad that I thought was fully working, but after a big investigation I've found that my renders are faulty to the extent that not only can't I print with Repetier Host, but if I print in MatterControl it appears to slice and print fine but after I've used 20grams or so of filament, my RAMPS board just extrudes but with no more effector movement. Tracing all this back, I have duplicate facets that I've found using either netfab or meshlab. The meshes look perfect from the outside. I can run a delete duplicate facets command which leaves triangles of random orientation and then manually correct them but this is very tedious, my latest model has about 2500 triangles. I'd like to avoid generating the coordinate list externally to Openscad but it's quite a mission already. Currently, if you imagine a flat underside and top side, with a math generated mesh stretching between, then I'm calling polyhedron once for each top/bottom segment pair and once for each level's triangle pair per side per level. I've seen http://www.thingiverse.com/thing:8742/#files <http://www.thingiverse.com/thing:8742/#files> which seems to call polyhedron for each independent facet, but I'm concerned that my render is possibly confusing vertices between triangles of different polyhedron calls as being part of new co-incident triangles that I don't actually want. rawradius=7.5; levs=3 ; //min for test levstep=12; sides=4; //min for test x_tra=16; step=360/sides; //translate([0,0,120]){%cube ([120,10,240],center=true);} //profile test function completed(k)=(((k+1)/(levs+1))); //levels completed fraction of 1 function scle(l) = (sin(completed(l)*65+90)); //height scale, terminate before 90 deg function offset(a,d)=(((rawradius*x_tra/2)-d*5) -scle(d)* rawradius*x_tra ); function x(a,d) =( scle(d)* rawradius*x_tra * abs(sin(a/2))+offset(a,d) ); function y(a,d) =(scle(d)*rawradius*0.6 * sin(a)); //*(sin(a))*1.4 pa=[for(lev=[0:levs+1]) for (a = [0:step:360+step]) [ a == (360+step) ? 0+offset(a,lev) +10: x(a,lev), //x a == (360+step) ? 0 : y(a,lev), //y lev*levstep //-cos(lev*9)*levstep*14 // ] ]; nxtl=sides+2; for (level = [0:levs] , a = [0 : 1 : ((360/step)-1)]){side(a,level);} for (a = [0 : 1 : ((360/step))]){bottom_top(a);} module bottom_top(a){ polyhedron(points=pa,faces= [[sides+1,a+1,a], //base triangles [(levs+1)*nxtl+sides+1,a+(levs+1)*nxtl,a+(levs+1)*nxtl+1] //top triangles ]); } module side(a,level){ polyhedron(points=pa,faces= [[a+level*nxtl,a+(level+1)*nxtl+1,a+(level+1)*nxtl], //side segment triangles [a+level*nxtl,a+level*nxtl+1,a+(level+1)*nxtl+1]//side segment triangles ]); } I've since found that I can run the "invert negative shells" script on netfab, apply and then select all, flip triangles and then apply. This gives me a valid model. However, on a fine mesh, I suspect that the duplicate triangles are wasting render time and I suspect my implementation is rather cumbersome with the complete points list defined at each polyhedron call but only a partial point order definition at each call. Is polyhedron usage documented more fully anywhere other than on the normal openscad wiki? Do I have to define ALL points and point orders for a single completed polyhedron with one polyhedron command? At the moment, I'm trying to wrap my head around reformatting the point order lists as multiple list comprehensions encapsulated in the point order part of the polyhedron statement but the syntax is messing with my head. -- View this message in context: http://forum.openscad.org/Polyhedron-issue-tp11003.html Sent from the OpenSCAD mailing list archive at Nabble.com.
NH
nop head
Sun, Jan 11, 2015 9:37 AM

Yes you need to define a complete solid, closed polyhedron, i.e. 2
manifold, in each call of polyhedron.

I think the only case where you can get away with parts of polygons is if
you pass them to hull, but the shape has to be convex.

On 11 January 2015 at 08:51, fluidity rael@xtra.co.nz wrote:

Hi all.
I had a polyhedron generation program all running natively in openscad that
I thought was fully working, but after a big investigation I've found that
my renders are faulty to the extent that not only can't I print with
Repetier Host, but if I print in MatterControl it appears to slice and
print
fine but after I've used 20grams or so of filament, my RAMPS board just
extrudes but with no more effector movement. Tracing all this back, I have
duplicate facets that I've found using either netfab or meshlab. The meshes
look perfect from the outside.

I can run a delete duplicate facets command which leaves triangles of
random
orientation and then manually correct them but this is very tedious, my
latest model has about 2500 triangles. I'd like to avoid generating the
coordinate list externally to Openscad but it's quite a mission already.
Currently, if you imagine a flat underside and top side, with a math
generated mesh stretching between, then I'm calling polyhedron once for
each
top/bottom segment pair and once for each level's triangle pair per side
per
level. I've seen  http://www.thingiverse.com/thing:8742/#files
http://www.thingiverse.com/thing:8742/#files  which seems to call
polyhedron for each independent facet, but I'm concerned that my render is
possibly confusing vertices between triangles of different polyhedron calls
as being part of new co-incident triangles that I don't actually want.

rawradius=7.5;
levs=3 ;                //min for test
levstep=12;
sides=4;        //min for test
x_tra=16;
step=360/sides;
//translate([0,0,120]){%cube ([120,10,240],center=true);} //profile test

function completed(k)=(((k+1)/(levs+1))); //levels completed fraction of 1
function scle(l) = (sin(completed(l)65+90)); //height scale, terminate
before 90 deg
function offset(a,d)=(((rawradius
x_tra/2)-d5) -scle(d) rawradiusx_tra
);
function x(a,d) =( scle(d)
rawradiusx_tra * abs(sin(a/2))+offset(a,d) );
function y(a,d) =(scle(d)rawradius0.6 * sin(a));  //
(sin(a))*1.4

pa=[for(lev=[0:levs+1]) for (a = [0:step:360+step])
[
a == (360+step) ? 0+offset(a,lev) +10: x(a,lev), //x
a == (360+step) ? 0 : y(a,lev), //y
levlevstep    //-cos(lev9)levstep14        //
]
];

nxtl=sides+2;

for (level = [0:levs] , a = [0 : 1 : ((360/step)-1)]){side(a,level);}
for (a = [0 : 1 : ((360/step))]){bottom_top(a);}

module bottom_top(a){
polyhedron(points=pa,faces=
[[sides+1,a+1,a], //base triangles
[(levs+1)*nxtl+sides+1,a+(levs+1)*nxtl,a+(levs+1)nxtl+1] //top triangles
]);
}
module side(a,level){
polyhedron(points=pa,faces=
[[a+level
nxtl,a+(level+1)nxtl+1,a+(level+1)nxtl], //side segment
triangles
[a+level
nxtl,a+level
nxtl+1,a+(level+1)*nxtl+1]//side segment triangles
]);
}

I've since found that I can run the "invert negative shells" script on
netfab, apply and then select all, flip triangles and then apply. This
gives
me a valid model. However, on a fine mesh, I suspect that the duplicate
triangles are wasting render time and I suspect my implementation is rather
cumbersome with the complete points list defined at each polyhedron call
but
only a partial point order definition at each call.

Is polyhedron usage documented more fully anywhere other than on the normal
openscad wiki?
Do I have to define ALL points and point orders for a single completed
polyhedron with one polyhedron command?
At the moment, I'm trying to wrap my head around reformatting the point
order lists as multiple list comprehensions encapsulated in the point order
part of the polyhedron statement but the syntax is messing with my head.

--
View this message in context:
http://forum.openscad.org/Polyhedron-issue-tp11003.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Yes you need to define a complete solid, closed polyhedron, i.e. 2 manifold, in each call of polyhedron. I think the only case where you can get away with parts of polygons is if you pass them to hull, but the shape has to be convex. On 11 January 2015 at 08:51, fluidity <rael@xtra.co.nz> wrote: > Hi all. > I had a polyhedron generation program all running natively in openscad that > I thought was fully working, but after a big investigation I've found that > my renders are faulty to the extent that not only can't I print with > Repetier Host, but if I print in MatterControl it appears to slice and > print > fine but after I've used 20grams or so of filament, my RAMPS board just > extrudes but with no more effector movement. Tracing all this back, I have > duplicate facets that I've found using either netfab or meshlab. The meshes > look perfect from the outside. > > I can run a delete duplicate facets command which leaves triangles of > random > orientation and then manually correct them but this is very tedious, my > latest model has about 2500 triangles. I'd like to avoid generating the > coordinate list externally to Openscad but it's quite a mission already. > Currently, if you imagine a flat underside and top side, with a math > generated mesh stretching between, then I'm calling polyhedron once for > each > top/bottom segment pair and once for each level's triangle pair per side > per > level. I've seen http://www.thingiverse.com/thing:8742/#files > <http://www.thingiverse.com/thing:8742/#files> which seems to call > polyhedron for each independent facet, but I'm concerned that my render is > possibly confusing vertices between triangles of different polyhedron calls > as being part of new co-incident triangles that I don't actually want. > > rawradius=7.5; > levs=3 ; //min for test > levstep=12; > sides=4; //min for test > x_tra=16; > step=360/sides; > //translate([0,0,120]){%cube ([120,10,240],center=true);} //profile test > > function completed(k)=(((k+1)/(levs+1))); //levels completed fraction of 1 > function scle(l) = (sin(completed(l)*65+90)); //height scale, terminate > before 90 deg > function offset(a,d)=(((rawradius*x_tra/2)-d*5) -scle(d)* rawradius*x_tra > ); > function x(a,d) =( scle(d)* rawradius*x_tra * abs(sin(a/2))+offset(a,d) ); > function y(a,d) =(scle(d)*rawradius*0.6 * sin(a)); //*(sin(a))*1.4 > > pa=[for(lev=[0:levs+1]) for (a = [0:step:360+step]) > [ > a == (360+step) ? 0+offset(a,lev) +10: x(a,lev), //x > a == (360+step) ? 0 : y(a,lev), //y > lev*levstep //-cos(lev*9)*levstep*14 // > ] > ]; > > nxtl=sides+2; > > for (level = [0:levs] , a = [0 : 1 : ((360/step)-1)]){side(a,level);} > for (a = [0 : 1 : ((360/step))]){bottom_top(a);} > > module bottom_top(a){ > polyhedron(points=pa,faces= > [[sides+1,a+1,a], //base triangles > [(levs+1)*nxtl+sides+1,a+(levs+1)*nxtl,a+(levs+1)*nxtl+1] //top triangles > ]); > } > module side(a,level){ > polyhedron(points=pa,faces= > [[a+level*nxtl,a+(level+1)*nxtl+1,a+(level+1)*nxtl], //side segment > triangles > [a+level*nxtl,a+level*nxtl+1,a+(level+1)*nxtl+1]//side segment triangles > ]); > } > > I've since found that I can run the "invert negative shells" script on > netfab, apply and then select all, flip triangles and then apply. This > gives > me a valid model. However, on a fine mesh, I suspect that the duplicate > triangles are wasting render time and I suspect my implementation is rather > cumbersome with the complete points list defined at each polyhedron call > but > only a partial point order definition at each call. > > Is polyhedron usage documented more fully anywhere other than on the normal > openscad wiki? > Do I have to define ALL points and point orders for a single completed > polyhedron with one polyhedron command? > At the moment, I'm trying to wrap my head around reformatting the point > order lists as multiple list comprehensions encapsulated in the point order > part of the polyhedron statement but the syntax is messing with my head. > > > > -- > View this message in context: > http://forum.openscad.org/Polyhedron-issue-tp11003.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
F
fluidity
Sun, Jan 11, 2015 9:49 AM

Thanks nophead,
very inconvenient but I may work on it further if I get bored... on holiday
for a couple of weeks.
This is the finished object after repair anyway:
http://www.thingiverse.com/thing:630485
Graham

--
View this message in context: http://forum.openscad.org/Polyhedron-issue-tp11003p11005.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Thanks nophead, very inconvenient but I may work on it further if I get bored... on holiday for a couple of weeks. This is the finished object after repair anyway: http://www.thingiverse.com/thing:630485 Graham -- View this message in context: http://forum.openscad.org/Polyhedron-issue-tp11003p11005.html Sent from the OpenSCAD mailing list archive at Nabble.com.
F
fluidity
Sun, Jan 11, 2015 10:50 AM

Solved.

One polyhedron call with flattened concatenated point order lists for end
facets and side facets.
Now renders super fast with no need to switch to wire frame mode first.

Solution:
rawradius=7.5;
levs=19 ;                //test
levstep=12;
sides=120;        //test
x_tra=16;
step=360/sides;
//translate([0,0,120]){%cube ([120,10,240],center=true);} //profile test

function completed(k)=(((k+1)/(levs+1))); //levels completed fraction of 1
function scle(l) = (sin(completed(l)65+90)); //height scale, terminate
before 90 deg
function offset(a,d)=(((rawradius
x_tra/2)-d5) -scle(d) rawradiusx_tra );
function x(a,d) =( scle(d)
rawradiusx_tra * abs(sin(a/2))+offset(a,d) );
function y(a,d) =(scle(d)rawradius0.6 * sin(a));  //
(sin(a))*1.4

pa=[for(lev=[0:levs+1]) for (a = [0:step:360+step])
[
a == (360+step) ? 0+offset(a,lev) +10: x(a,lev), //x
a == (360+step) ? 0 : y(a,lev), //y
levlevstep //-cos(lev9)levstep14 //
]
];

nxtl=sides+2;

side_orders=[for(level=[0:levs]) for (a = [0:1:360/step-1])
[ [a+level*nxtl,a+(level+1)nxtl+1,a+(level+1)nxtl],          //side
segment triangles
[a+level
nxtl,a+level
nxtl+1,a+(level+1)*nxtl+1]]
];
end_orders=[for (a = [0:1:360/step])
[[sides+1,a+1,a],    //    base triangles
[(levs+1)*nxtl+sides+1,a+(levs+1)*nxtl,a+(levs+1)*nxtl+1]]  //top
triangles
];
function flatten(l) = [ for (a = l) for (b = a) b ] ;
eo=flatten(end_orders);
so=flatten(side_orders);
all_orders=flatten([eo,so]);
polyhedron(points=pa,faces=all_orders);

--
View this message in context: http://forum.openscad.org/Polyhedron-issue-tp11003p11006.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Solved. One polyhedron call with flattened concatenated point order lists for end facets and side facets. Now renders super fast with no need to switch to wire frame mode first. Solution: rawradius=7.5; levs=19 ; //test levstep=12; sides=120; //test x_tra=16; step=360/sides; //translate([0,0,120]){%cube ([120,10,240],center=true);} //profile test function completed(k)=(((k+1)/(levs+1))); //levels completed fraction of 1 function scle(l) = (sin(completed(l)*65+90)); //height scale, terminate before 90 deg function offset(a,d)=(((rawradius*x_tra/2)-d*5) -scle(d)* rawradius*x_tra ); function x(a,d) =( scle(d)* rawradius*x_tra * abs(sin(a/2))+offset(a,d) ); function y(a,d) =(scle(d)*rawradius*0.6 * sin(a)); //*(sin(a))*1.4 pa=[for(lev=[0:levs+1]) for (a = [0:step:360+step]) [ a == (360+step) ? 0+offset(a,lev) +10: x(a,lev), //x a == (360+step) ? 0 : y(a,lev), //y lev*levstep //-cos(lev*9)*levstep*14 // ] ]; nxtl=sides+2; side_orders=[for(level=[0:levs]) for (a = [0:1:360/step-1]) [ [a+level*nxtl,a+(level+1)*nxtl+1,a+(level+1)*nxtl], //side segment triangles [a+level*nxtl,a+level*nxtl+1,a+(level+1)*nxtl+1]] ]; end_orders=[for (a = [0:1:360/step]) [[sides+1,a+1,a], // base triangles [(levs+1)*nxtl+sides+1,a+(levs+1)*nxtl,a+(levs+1)*nxtl+1]] //top triangles ]; function flatten(l) = [ for (a = l) for (b = a) b ] ; eo=flatten(end_orders); so=flatten(side_orders); all_orders=flatten([eo,so]); polyhedron(points=pa,faces=all_orders); -- View this message in context: http://forum.openscad.org/Polyhedron-issue-tp11003p11006.html Sent from the OpenSCAD mailing list archive at Nabble.com.
MK
Marius Kintel
Sun, Jan 11, 2015 5:46 PM

Hi Graham,

Just a few comments to clear things up:

First, there’s a small bug in your last code; you forgot the -1 on line 29:
end_orders=[for (a = [0:1:360/step-1])

It looks like this just creates some degenerate (2-vertex) triangles, but it’s probably good to clean it up.

The reason why your first version failed is that, when creating a union of separate polyhedrons, it’s crucial that the vertices where they join are exactly the same. If not, small floating point differences will be preserved and cause microscopic caps which again confuses the underlying geometry engine as the geometry isn’t manifold.
You’re using the development snapshot and this is one of the remaining issues to be resolved before release. I’m not sure which version you use, but the current master should behave better than what you describe. It works perfectly for me. This behavior was updated very late december I think.

I’ll look more closely at your design later as this would be good to add to our test framework.

-Marius

Hi Graham, Just a few comments to clear things up: First, there’s a small bug in your last code; you forgot the -1 on line 29: end_orders=[for (a = [0:1:360/step-1]) It looks like this just creates some degenerate (2-vertex) triangles, but it’s probably good to clean it up. The reason why your first version failed is that, when creating a union of separate polyhedrons, it’s crucial that the vertices where they join are _exactly_ the same. If not, small floating point differences will be preserved and cause microscopic caps which again confuses the underlying geometry engine as the geometry isn’t manifold. You’re using the development snapshot and this is one of the remaining issues to be resolved before release. I’m not sure which version you use, but the current master should behave better than what you describe. It works perfectly for me. This behavior was updated very late december I think. I’ll look more closely at your design later as this would be good to add to our test framework. -Marius