-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mesh from closed polylines #16
Comments
Starling's pmDecompose component works pretty well for the purpose of creating a Plankton mesh from several polylines. Perhaps we should add a simple component that wraps up the code below? # V: list of Point3d
# F: tree of int
import clr
clr.AddReferenceToFile("Plankton.dll")
import Plankton
pmesh = Plankton.PlanktonMesh()
for pt in V:
pmesh.Vertices.Add(pt.X, pt.Y, pt.Z)
for face in F.Branches:
face = list(face)[:-1] # see comment below
pmesh.Faces.AddFace(face) |
Actually there's a bug in the Starling component. It counts all the vertices in a closed polyline (where the first vertex appears again at the end). |
Not currently. The above definition using Starling was the best solution I've achieved so far. |
Provided the vertices are exactly coincident, I've been using: PlanktonMesh PMeshFromPolylines(List<Polyline> faces)
{
var pMesh = new PlanktonMesh();
//add n-gon faces
var verts = new List<Point3d>();
for (int i = 0; i < faces.Count; i++)
{
var currFace = new List<int>();
for (int j = 0; j < faces[i].Count - 1; j++)
{
var currPt = faces[i].PointAt(j);
var id = verts.IndexOf(currPt);
if (id < 0)
{
//push a vertex to list
//push that index to current face
pMesh.Vertices.Add(currPt.X, currPt.Y, currPt.Z);
verts.Add(currPt);
currFace.Add(pMesh.Vertices.Count - 1);
}
else
{
//push this index to current face
currFace.Add(id);
}
}
pMesh.Faces.AddFace(currFace);
}
return pMesh;
} And to convert a PlanktonMesh to polylines: List<Polyline> PolylinesFromPMesh(PlanktonMesh pMesh)
{
var faces = new List<Polyline>();
for (int i = 0; i < pMesh.Faces.Count; i++)
{
var tmpCurve = new Polyline();
var faceCirculator = pMesh.Halfedges.GetFaceCirculator(pMesh.Faces[i].FirstHalfedge);
foreach (var id in faceCirculator)
{
var idx = pMesh.Halfedges[id].StartVertex;
var tmpPt = new Point3d(pMesh.Vertices[idx].X, pMesh.Vertices[idx].Y, pMesh.Vertices[idx].Z);
tmpCurve.Add(tmpPt);
}
//close the curve
tmpCurve.Add(tmpCurve.PointAt(0));
faces.Add(tmpCurve);
}
return faces;
} |
Just found the ToPolyline method....I guess that works too ;) |
Hi @pearswj, I attempted to duplicate your example using GhPython, but I got the error "Data conversion failed from Goo to PlanktonMesh" on the output. Any ideas? Within the Python window I can print pmesh.Vertices[0].X for example and it works fine. After I get this quad example working, I would like to attempt with ngon faces >4 sides. |
Hey @viper4049, I just tried this again in Rhino 5, Rhino WIP and Rhino WIP for Mac. Only in Rhino WIP for Windows do I see your error. I'll pass this on to @piac as he's responsible for the new Python script component in Grasshopper 1.0. |
@viper4049, I've moved this particular issue to youtrack. |
@pearswj Check what happens in your |
One addition that I think is required is this one:
Also, I think this needs to happen at the beginning of your code. |
@viper4049, just to keep you in the loop... I managed to get this working by making sure that the python script was referencing the same Plankton.dll that Grasshopper loads*. clr.AddReferenceToFileAndPath("C:\Users\Will\AppData\Roaming\Grasshopper\Libraries\Plankton.dll") *Actually, Grasshopper loads Plankton.gha, which in turn references Plankton.dll. But you get the idea... |
You can also try the following if, like me, hard coded paths make you shiver: import Grasshopper
appdata = Grasshopper.Folders.DefaultAssemblyFolder
import clr
clr.AddReferenceToFileAndPath(appdata + "Plankton.dll") |
Excellent, thanks - the python script now works! This ability to build ngon pmeshes was exactly what I was looking for. Using predefined cells from LunchBox everything works fine. However when I attempt to make my own mesh edge loops, only parts of the pmesh are created. My end goal is to be able to feed any polyline graph (simply connected, not in loops) and create an ngon pmesh. I'm using curves splitting a surface to get the connected mesh edge loops, then creating a tree of polylines to feed pmDecompose. If you have time, would you be able to check if you see the same behavior? If not, I can try updating my libraries. If so, any ideas? When I bake the polylines going into pmDecompose everything looks well behaved (even in the areas where the pmesh isn't created). Perhaps it's a tolerance issue with the vertices not lining up perfectly? I tried Topologizer with a tolerance but that didn't help anything. Here's the link to my GH file (for some reason it wouldn't let me upload). |
@viper4049, it's the face winding directions that are causing the problem. Plankton only handles manifold meshes, i.e. meshes which have a front and a back. This orientation is determined by the "right-hand rule" i.e. if the vertices of a face are ordered counter-clockwise then the face normal will be out of the page/screen. You could try the following: if pmesh.Faces.AddFace(face) < 0: # AddFace returns -1 if the face couldn't be added
pmesh.Faces.AddFace(reversed(face)) # try adding the opposite face But, this won't work all the time. To do this properly, you need to make the face-winding uniform before building the mesh: I did this here by comparing the normal of the original surface (sampled from the centroid of each face polyline) with the cross product of the first two edges of each face polyline. The comparison uses the dot product which will be either positive or negative, depending on whether the winding of the face polyline agrees with the right hand rule, or not. |
You can also use Weaverbird's Unify Face Windings for that. It works also on polylines that meet at vertices. |
Yes, do that! @piac you're a genius 😎. |
Perfect, simpler the better! Thanks so much for your help, I learned a lot through this exercise. |
I wrote up this example here in case anyone else was looking for the same thing. |
Create a mesh from a number of closed polylines.
A mesh from a closed polyline is straightforward:
Creating a mesh from several polylines could be done in the same way with a secondary procedure to merge duplicate vertices. Duplicates could be merged either before (faster) or after (more flexible) the faces are added.
The text was updated successfully, but these errors were encountered: