Closed davestasiuk closed 9 years ago
Dave, thanks for this! Glad my instructions were easy to follow. My immediate thought is that we should consolidate these two functions into one Dual function. Perhaps we could use optional parameters for the handling of boundaries (I think the default behaviour should ignore boundary vertices when creating dual faces).
I think those are good ideas on both counts. The two ways I wrote the dual - this one, without the boundaries, and the other one, with - are quite different in a few key places. I suppose that we could just keep them both, and then just gate between them with an optional RetainBoundary bool...but as you pointed out in the other one, the means of sorting the naked edges wasn't particularly good, and in any event, it doesn't seem particularly elegant to double up on so much, though.
@davestasiuk We should add some tests for this also, checking global feature counts (i.e. do we have the right number of "active" halfedges in the dual) and perhaps some local checks too, around boundaries especially, to check everything has been linked up correctly.
As an aside, I've moved the automated builds to http://pearswj.co.uk/builds/plankton (look for Branch Ref: pr/23).
I still think we should consolidate these two methods into one Dual function, with optional boundary edge treatment. Can we hold back on shouting about the PlanktonDual method so that we don't cause too many problems when we come to deprecate it?
/cc @Dan-Piker @davestasiuk
Agreed. I put it in because I wanted be able to use this on open meshes, but after testing it seems that there are actually some problems with this PlanktonDual method where the PrevHalfedge is not correctly assigned. So let's revert the merge until finding what the problem is, and then make it just a single Dual method that works for both.
Hey guys- I'll be happy to have a look at this, hopefully a bit later on in the week. We are into production mode on our current project, so I am underwater with that. It's been a goal of mine though to get to this. I also will send you a note on a separate Plankton topic I've been thinking about.
Hi @davestasiuk I'm using your PlanktonMesh.PlanktonDual method. Did you ever figure out the issue @Dan-Piker found with the PrevHalfEdge not being assigned?
I'm available to help debug if an extra pair of eyes would be useful.
Hey @harrilewis, PlanktonMesh.Dual()
does work on open meshes. The current method is much more simplistic than Dave's contribution. It produces the same output as Weaverbird's "DualGraph", i.e. no dual-faces for boundary vertices on the primal mesh. Check out the code below for something that handles those boundary faces...
"""Plankton dual (creates faces for boundary vertices).
Inputs:
m: mesh as Rhino Mesh
Output:
a: dual mesh as Polylines
b: dual mesh as PlanktonMesh"""
__author__ = "will"
import rhinoscriptsyntax as rs
import Grasshopper
appdata = Grasshopper.Folders.DefaultAssemblyFolder
import clr
clr.AddReferenceToFileAndPath(appdata + "Plankton.dll")
clr.AddReferenceToFileAndPath(appdata + "Plankton.gha")
import Plankton
import PlanktonGh
clr.ImportExtensions(PlanktonGh.RhinoSupport)
m = x.ToPlanktonMesh()
#a = m.Dual().ToPolylines()
if not m.IsClosed():
dual = Plankton.PlanktonMesh()
# create vertices from face centers
for i in range(m.Faces.Count):
fc = m.Faces.GetFaceCenter(i)
dual.Vertices.Add(fc.X, fc.Y, fc.Z)
# create boundary vertices
for i in range(0, m.Halfedges.Count, 2):
v0 = m.Halfedges[i].StartVertex
v1 = m.Halfedges[m.Halfedges.GetPairHalfedge(i)].StartVertex
mid = (m.Vertices[v1].ToXYZ() + m.Vertices[v0].ToXYZ())
dual.Vertices.Add(mid.X * 0.5, mid.Y * 0.5, mid.Z * 0.5)
# create faces from the adjacent face indices of non-boundary vertices
for i in range(m.Vertices.Count):
if (m.Vertices.IsBoundary(i)):
hs = m.Vertices.GetHalfedges(i)
vs = []
for j in hs: # clockwise
if m.Halfedges[j].AdjacentFace > -1:
vs.append(m.Halfedges[j].AdjacentFace)
else:
# add extra vertices for dual-faces created from boundary vertices
k = m.Halfedges[j].PrevHalfedge
vs.append(int((k - (k % 2)) / 2) + m.Faces.Count)
vs.append(int((j - (j % 2)) / 2) + m.Faces.Count)
dual.Faces.AddFace(vs)
else:
dual.Faces.AddFace(m.Vertices.GetVertexFaces(i))
# dual.Compact()
else:
# use built-in Dual for closed meshes
dual = m.Dual()
a = dual.ToPolylines()
b = dual
Let me know if this is useful!
Hi @pearswj thanks for the above - very useful!
I was getting some funny runaway edges - I think the line:
j = m.Halfedges[j].NextHalfedge
should be removed - j should remain as the index of the halfedge in question.
@harrilewis you're totally right. Not sure how that crept in there; It's not in the script that I'm actually using! 🤷♂️ I'll edit it...
PlanktonMesh.PlanktonDual() now handles open meshes by including boundaries, and works cleanly with closed meshes. To be added is additional functionality for removing boundaries if desired. Also, boundary points are currently calculated as midpoints of the primal halfedges...making these perpendicular to the new face centers could be desirable.
Resolves #22.