With immutable variables, the only way I see to mark already processed
triangles is to generate the whole thing with new marks. And that is
inefficient.
I think I have a little chance to make it if I can create a list of neighbors
to unfold starting from the first one that I choose. It starts with its
direct neighbours, then continue with their neighbors and so on, but I
cannot see how to create that with OpenSCAD, I need to read more about list
comprehension.
--
Sent from: http://forum.openscad.org/
gilboonet wrote
I think I have a little chance to make it if I can create a list of
neighbors
to unfold starting from the first one that I choose. It starts with its
direct neighbours, then continue with their neighbors and so on, but I
cannot see how to create that with OpenSCAD, I need to read more about
list
comprehension.
...
I imagine the easiest way to do something like that in OpenSCAD would be
recursion. For example with a function that takes a partial net, tries to
add one face to the net, and then calls itself with the new partial net if
it works.
There are relatively simple shapes (like a small cube stacked on top of the
center of a big cube) that don't have 'one piece' nets. So it might make
sense to take a "breadth first" approach to flattening without overlaps, and
then looking for minimal cuts to make printable pieces from it.
--
Sent from: http://forum.openscad.org/
Here's a quick and dirty unfolder that I wrote. It uses a stupid method for
generating the unfolding tree that is unlikely to scale well. I think
recursion is necessary to make one with better scaling behavior.
I also don't have fancy polyhedra to hand for testing it, but it's still
cute with animation on.
unfold.scad http://forum.openscad.org/file/t2140/unfold.scad
--
Sent from: http://forum.openscad.org/
I don't think that this process is particularly horrible in terms of
efficiency. You have the polygon as a list of vertices and faces. You
first need to construct a list of the faces that are across each edge.
This can be done by enumerating the edges and then sorting the list. Then
you can look at a face and find the faces that are adjacent with a simple
list index. Tracking which faces have been placed already does of course
require updating a list, but it doesn't have to be a huge data structure,
just a simple list with one boolean entry per face. I wouldn't think you'd
want to do thousands of polygons, but this would be fine for moderate sized
cases, certainly it should be doable for <100 faces. Updating a length 100
list of booleans isn't going to be a huge time suck. I think checking
intersection is probably the most time consuming step, because you'll have
to check lots of segments as more of the net is assembled.
There are only two ways you could do this: recursion for C-style for loop.
The C-style for loop is paradoxically slower than recursion in my tests, and
can be harder to use than one would expect. I would do it with recursion.
It seems like the most complicated aspect of this would be maintaining a
stack, because you need to be able to pop the stack to return to the last
branch point as you search the tree.
Here's how it's possible to compute the faces that are associated with edges
using the BOSL2 library. This runs in 3s with 3500 faces, which should be a
lot more than you'd ever want to make a net for.
include<BOSL2/std.scad>
// Returns list of edges in sorted order with the pair of faces for each
edge
// edge table has the form
// [[v1,v2],[f1,f2]] the edge [v1,v2] connects f1 to f2
// vertices are indices into the vertex list and
faces
// indices into face list
// facetable
// entry i lists the edges that compose face i as indices into the edge
table above
function edge_faces(vnf) =
let(
faces=vnf[1],
// [v1,v2,face_index]
edgelist= [ for(faceind=idx(faces), j=[0:len(faces[faceind])-1])
let(
v1=faces[faceind][j],
v2=faces[faceind][(j+1)%len(faces[faceind])]
)
v1<v2 ? [v1,v2,faceind,j] : [v2,v1,faceind,j]
],
sedge = sort(edgelist),
edgetable = [for(i=[0:2:len(sedge)-1])
assert(sedge[i][0]==sedge[i+1][0] &&
sedge[i][1]==sedge[i+1][1],
str("Found unpaired edge, ",
sedge[i-1]," ",sedge[i]," ",
sedge[i+1]," ",sedge[i+2],"
",sedge[i+3]," ",sedge[i+4]," ",len(sedge)))
// add check for too many of the same edge?
[select(sedge[i],0,1), [sedge[i][2], sedge[i+1][2]]]],
facetable = group_data(subindex(sedge,2), [for(i=idx(sedge))
floor(i/2)], sortidx(sedge,[2,3]))
)
[edgetable,facetable];
// Function: group_data
// Given a vector of group numbers and a vector of values, produces an
// output with all the values in each group: [[v0_0,v0_1,v0_2,..],
[v1_0,v1_1,v1_2,...],...]
// The first list in the output will be all items corresponding to group 0,
the second list group 1, and
// so on. If no members exist for a group the empty list is output.
function group_data(group, value, sidx) =
assert(is_list(group) && is_list(value) &&
len(group)==len(value),"Must provide lists of matching length")
let(
sidx = is_def(sidx) ? sidx : sortidx(group),
cuts =[each repeat(0,1+group[sidx[0]]),
for(i=[1:len(group)-1]) let(delta =
group[sidx[i]]-group[sidx[i-1]]) each if (delta>0) repeat(i,delta),
len(group)]
)
[for(i=[0:len(cuts)-2])
[for(j=[cuts[i]:1:cuts[i+1]-1]) value[sidx[j]]]];
Ronaldo wrote
With immutable variables, the only way I see to mark already processed
triangles is to generate the whole thing with new marks. And that is
inefficient.
OpenSCAD mailing list
To unsubscribe send an email to
discuss-leave@.openscad
--
Sent from: http://forum.openscad.org/
NateTG wrote
Here's a quick and dirty unfolder that I wrote.
Thanks a lot for that script. I need to dig it as at first look I didn't
understand it.
NateTG wrote
I also don't have fancy polyhedra to hand for testing it
I have lots of low poly models that I usually use for my tests; it's easy to
grab polyhedron data from them :
--
Sent from: http://forum.openscad.org/
adrianv wrote
Here's how it's possible to compute the faces that are associated with
edges
using the BOSL2 library. This runs in 3s with 3500 faces, which should be
a
lot more than you'd ever want to make a net for.
Thank you too for the script, apparently recursion is the way to go. That's
very interesting for me as it introduces me to BOSL. 3500 faces is lots more
than my usual model, that's great that it runs so fast. Now I need to try to
understand your code. About running time of the process, I think that it's
only the unfolding that takes time, the rendering of the net with all
numbers also takes lot of time. At first I did it with text primitive, then
added a function to cache text injection, then replaced the built-in text
polygons with a minimalistic set of polygons, and finally (but not only to
improve speed, also to improve rendering quality) I rendered the net with
svg injection. With a 2000 faces model I ended with a svg containing 13K
lines (700 Ko).
--
Sent from: http://forum.openscad.org/
gilboonet wrote
I have lots of low poly models that I usually use for my tests; it's easy
to
grab polyhedron data from them :
Thanks, that helped me discover a bug. Line 51 of the script that I
uploaded should have been:
theta=$tatan2(untouw,unto*unfrom)
rather than
theta=$t*-((nfrom*nto > 0)? ...
--
Sent from: http://forum.openscad.org/