Get all ngons [SOLVED]
-
On 23/11/2016 at 03:27, xxxxxxxx wrote:
Is there a way for getting each group of ngon?
Here my first attempt who is working 90% time but that mean the obj need to be inserted into the document and is not optimized at all on huge mesh.
def deconnexion(obj) : doc = c4d.documents.GetActiveDocument() settings = c4d.BaseContainer() settings[c4d.MDATA_DISCONNECT_PRESERVEGROUPS] = False test = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_DISCONNECT, list = [obj], mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION, bc = settings, doc = doc) def get_ngnon(obj) : save_before = obj.GetClone() mode = doc.GetMode() doc.SetMode(c4d.Mpolygons) deconnexion(obj) selection = obj.GetPolygonS() selection.DeselectAll() buffer_all_ngons = [] poly_to_check = range(0,obj.GetPolygonCount()) for polygon_index in xrange(obj.GetPolygonCount()) : selection.DeselectAll() #Si notre l'index est dans le poly to check if polygon_index in poly_to_check: #On select notre poly selection.Select(polygon_index) # On selectionne les élements connecté c4d.CallCommand(12557) #Si il y a plus de 1 poly c'est que c'est un ngno if selection.GetCount() >= 2: count = op.GetPolygonCount() buffer = [] for i in xrange(count) : if selection.IsSelected(i) : if i in poly_to_check: poly_to_check.remove(i) buffer.append(i) buffer_all_ngons.append(buffer) doc.SetMode(mode) save_before.CopyTo(obj,0) return buffer_all_ngons
Here is another attempt here you can see my scene http://img4.hostingpics.net/pics/432338ngon.jpg
poly id 0 = quad
all other are ngonIn this attempt I only try to have all ngons.
But finaly I would like to have the same output as my first attempt.def get_ngon_v2(obj) : edge_ngon = list(set(obj.GetNgonEdgesCompact())) all_ngons = [] nbr = c4d.utils.Neighbor() nbr.Init(obj) for i in xrange(op.GetPolygonCount()) : pli = nbr.GetPolyInfo(i)["edge"] for edge in pli: if edge in edge_ngon: all_ngons.append(i) return list(set(all_ngons))
Thanks in advance
-
On 25/11/2016 at 09:54, xxxxxxxx wrote:
Hi,
Are you trying to get all polygons inside one N-gon?
You're first solution works with my tests but the second that uses PolygonObject.GetNgonEdgesCompact() can't work (the function doesn't return edge indices).
N-gon support is limited in Python. C++ API PolygonObject::GetAndBuildNgon() gives information for all N-gons of an object.
In Python it's only possible to get the number of N-gons via PolygonObject.GetNgonCount(). -
On 25/11/2016 at 11:04, xxxxxxxx wrote:
Not sure if this helps.
But here are a couple of scripts I've used to get n-gons.Example #1
#This script retrieves a list that contains n-gon information for each selected polygon import c4d def main() : obj = doc.GetActiveObject() if obj is None: return False ngons = [] EdgeS = obj.GetPolygonS() polyCount = obj.GetPolygonCount() allEdges = obj.GetNgonEdgesCompact() for poly in xrange(polyCount) : if EdgeS.IsSelected(poly) : selPoly = poly if allEdges[selPoly] !=0: #print "index: ",selPoly, "poly is an ngon" ngons.append(selPoly) print ngons c4d.EventAdd() if __name__=='__main__': main()
Example #2
#This script returns all of the polygons in an object that are n-gons using the mark option #Not fully tested!! Might not work in every situation!! import c4d def main() : obj = doc.GetActiveObject() polys = obj.GetAllPolygons() polyCount = obj.GetPolygonCount() nbr = c4d.utils.Neighbor() nbr.Init(obj) for poly in xrange(polyCount) : pli = nbr.GetPolyInfo(poly) #print pli["mark"] m = pli["mark"] if m[0]==False and m[1]==True and m[2] == True and m[3]==True: print "polygonID: ", poly, "is an ngon" else: print "Not ngon" c4d.EventAdd() if __name__=='__main__': main()
-ScottA
-
On 27/11/2016 at 08:37, xxxxxxxx wrote:
Yes I'm trying to get all polygons inside one N-Gon.
I thinked about getting all ngon and then with GepolyInfo if polygon is in the all_ngon_list than do something but the porblem is if all ngon are connected that will never tell me wich polygon belong to wich ngon.Yes my first function work but not in all case. Anyway I will use it and optimize it using GetPolyInfo instead of selection which is not a great things ^^
Yeah maybe I will port my code to C++ but I'm not an expert in C++ ^^'.
Hooo so what are the value returned by GetNgonEdgesCompact()?.
Anyway thanks for your highlight.Thanks scotta for yours scripts but both of them are not usefull in my case. Since my script change uv randomly by polygon. I need to know which polygon belong to wich ngon(like I do in my first script).
Then I can random a whole ngon with the same seed.So I think I will stick to my first try and jsut optimize the selection function
-
On 28/11/2016 at 01:49, xxxxxxxx wrote:
For people who want to try here is the optimized function. Maybe to much speedy for float in python since the first method( get_ngonv2) return me an execution time of 0.0. But I guess it's a float error.
import c4d import time def deconnexion(obj) : doc = c4d.documents.GetActiveDocument() settings = c4d.BaseContainer() settings[c4d.MDATA_DISCONNECT_PRESERVEGROUPS] = False test = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_DISCONNECT, list = [obj], mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION, bc = settings, doc = doc) def get_ngon(obj) : save_before = obj.GetClone() mode = doc.GetMode() doc.SetMode(c4d.Mpolygons) deconnexion(obj) selection = obj.GetPolygonS() selection.DeselectAll() buffer_all_ngons = [] poly_to_check = range(0,obj.GetPolygonCount()) for polygon_index in xrange(obj.GetPolygonCount()) : selection.DeselectAll() if polygon_index in poly_to_check: selection.Select(polygon_index) c4d.CallCommand(12557) if selection.GetCount() >= 2: count = obj.GetPolygonCount() buffer = [] for i in xrange(count) : if selection.IsSelected(i) : if i in poly_to_check: poly_to_check.remove(i) buffer.append(i) buffer_all_ngons.append(buffer) doc.SetMode(mode) save_before.CopyTo(obj,0) return buffer_all_ngons def get_poly_info(nbr,id_poly) : poly_connected = [] pli = nbr.GetPolyInfo(id_poly)["face"] for face in pli: if face != c4d.NOTOK: poly_connected.append(face) return list(set(poly_connected)) def get_ngonv3(obj) : save_before = obj.GetClone() deconnexion(obj) all_poly_done = [] all_ngons = [] nbr = c4d.utils.Neighbor() nbr.Init(obj) for i in xrange(obj.GetPolygonCount()) : poly_to_do = [] poly_ngon = [] poly_to_do.append(i) for id_poly in poly_to_do: if not id_poly in all_poly_done: buffer_poly_info = get_poly_info(nbr,id_poly) poly_to_do += buffer_poly_info poly_ngon.append(id_poly) all_poly_done.append(id_poly) if len(poly_ngon) : all_ngons.append(poly_ngon) save_before.CopyTo(obj,0) return all_ngons def main() : t = time.time() doc = c4d.documents.GetActiveDocument() obj = doc.GetActiveObject() print get_ngonv3(obj) print time.time() - t c4d.EventAdd() t = time.time() doc = c4d.documents.GetActiveDocument() obj = doc.GetActiveObject() print get_ngon(obj) print time.time() - t if __name__=='__main__': main()
As said before in some case it fail. Then be carefull using it !
But looks like no one get a better idea so I will deal with it and mark it as solved.
-
On 30/11/2016 at 03:31, xxxxxxxx wrote:
Hi!
I've investigated the return values of PolygonObject.GetNgonEdgesCompact(). These give information on Ngon edges for each polygon so this function can be used to retrieve all Ngons from a polygon object.
The function returns a value (bit masked) for each polygon telling which of its edge(s) are actually from an Ngon. If the value is 0 the polygon isn't inside an Ngon.
Note the statement in the docs about the hidden Ngon edges is wrong. It only gives information on Ngon edges.
To check if a polygon edge is an Ngon edge use the condition:edgeValue & (1 << edgeIndex) == 0
Where edgeValue is the value for a polygon returned by GetNgonEdgesCompact() and edgeIndex the polygon edge index between 0 and 3.
The following script selects all Ngon edges of a polygon object.
The function GetNgonEdges() is the most important part where the conversion from GetNgonEdgesCompact() 'local' edges values are converted to the actual polygon object indices.import c4d from c4d import utils def GetNgonEdges(op, nbr) : # Edge selection for the Ngon edges edgeSel = c4d.BaseSelect() # Retrieve Ngon edges 'local' values for each polygon edgesInfo = op.GetNgonEdgesCompact() # Process each polygon polyCount = op.GetPolygonCount() for polyIdx in xrange(polyCount) : edgeValue = edgesInfo[polyIdx] if edgeValue == 0: continue # Retrieve polygon and polygon information poly = op.GetPolygon(polyIdx) polyInfo = nbr.GetPolyInfo(polyIdx) # For each edge of polygon for edgeIdx in xrange(4) : # Check if edge has been already processed if polyInfo["mark"][edgeIdx]: continue # Check if polygon edge is an Ngon edge if edgeValue & (1 << edgeIdx) == 0: # Select polygon object Ngon edge # polyInfo['edge'][edgeIdx] gives the polygon object edge index for the polygon edge at edgeIdx edgeSel.Select(polyInfo['edge'][edgeIdx]) return edgeSel def main() : if op is None or op.GetType() != c4d.Opolygon: return if op.GetNgonCount() == 0: return # Set Edges mode doc.SetMode(c4d.Medges) # Create and initialize a Neigbor instance for the object nbr = utils.Neighbor() nbr.Init(op) # Process polygon object and obtain Ngon edges edgeSel = GetNgonEdges(op, nbr) # Select Ngon edges op.SetSelectedEdges(nbr, edgeSel, c4d.EDGESELECTIONTYPE_SELECTION) c4d.EventAdd() if __name__=='__main__': main()
Finally, GetNgonEdgesCompact() gives the info needed on Ngons and using it plus processing its data is fast.