Turning selection tags into separate objects
-
On 16/07/2015 at 16:40, xxxxxxxx wrote:
Hi,
I imported a fractured piece of geometry as a single object and would like to turn each chunk into a unique object with a python script. Luckily i have selection tags for each chunk. Unfortunately I dont know how to iterate through those tags and get their polygons split up.
This is what I would like to do:
1. collect all polygon selection tags that are called "name_piece*", (eg name_piece0, name_piece1, ...)
2. grab their polygon selections and run a "split" modeling commmand on each of them
Would be great if someone could show me how to set this up!
________________________________Here is what I got so far (some of this is from https://developers.maxon.net/forum/topic/6464/6947_load-edge-selection) :
import c4d
from c4d import utils
from c4d import guidef findTag(obj, tagtype) :
result = []
tags = obj.GetTags()
for tag in tags:
if tag.CheckType(tagtype) :
# if .GetName() == "name_piece*"
result.append(tag)
return resultdef main() :
asset_obj = doc.GetActiveObject()
if asset_obj == None:
returndoc.StartUndo()
doc.AddUndo(c4d.UNDOTYPE_CHANGE, asset_obj)
settings0 = c4d.BaseContainer()
res0 = utils.SendModelingCommand(command = c4d.MCOMMAND_CURRENTSTATETOOBJECT,
list = [asset_obj],
mode = c4d.MODELINGCOMMANDMODE_ALL,
bc = settings0,
doc = doc)
if res0:
doc.InsertObject(res0[0])
sel_obj = doc.GetFirstObject()
if sel_obj == None:
returnsel_obj.Remove()
c4d.EventAdd()
# sel_tag = findTag(sel_obj, c4d.Tpolygonselection, name_piece)[0]
doc.EndUndo()
if __name__=='__main__':
main() -
On 17/07/2015 at 05:10, xxxxxxxx wrote:
Hello and welcome,
if you want to get all tags that match a certain name pattern you have to use the functionality of the Python string class (like "Does Python have a string contains method?").
You find an example on how to use the split command with SendModelingCommand() in this thread:
best wishes,
Sebastian -
On 17/07/2015 at 06:23, xxxxxxxx wrote:
Hi Konstantin,
if you have further questions regarding the post, sebastian linked you to, or about the provided script, feel free to ask.
I hope this script answers your questions.
Best wishes
Martinimport c4d from c4d import utils def main() : #validate object and selectiontag if not op:return if not op.IsInstanceOf(c4d.Opolygon) :return tags = op.GetTags() #deselect current polygonselection and store a backup to reselect polyselection = op.GetPolygonS() store = c4d.BaseSelect() polyselection.CopyTo(store) #define the name to search for name = "name-piece" #loop through the tags and check if name and type fits #if so split t = op.GetFirstTag() while t: if t.GetType() == c4d.Tpolygonselection: if name in t.GetName() : #select polygons from selectiontag tagselection = t.GetBaseSelect() tagselection.CopyTo(polyselection) #split: polygonselection to a new object sec = utils.SendModelingCommand(command=c4d.MCOMMAND_SPLIT, list=[op], mode=c4d.MODELINGCOMMANDMODE_POLYGONSELECTION, doc=doc) if not sec: return print sec sec[0].InsertAfter(op) t = t.GetNext() store.CopyTo(polyselection) c4d.EventAdd() if __name__=='__main__': main()
-
On 17/07/2015 at 10:13, xxxxxxxx wrote:
thank you sebastian and martin for your support!
i overlooked that thread the other night. i will take my time to go through it.
however the script only seems to work on objects with a few selection tags. after hitting "active state to object" the fractured geometry i had created with houdini engine unfortunately holds dozens, if not hundreds of selection tags which makes the script freeze Cinema 4D.
how could this be solved? maybe by putting the while loop in a function of its own and only calling it for lets say 5 pieces at a time? Or calling the script from another script? or by deleting the selection tags before copying?
i linked the geometry and switched the name in the script to "name_piece" for it to work.
http://www.konstantinmagnus.de/files/chunks.c4d
thanks for your help and please tell me in case my whole approach is cumbersome.
-
On 18/07/2015 at 12:56, xxxxxxxx wrote:
Hi Konstantin,
if you spend more time and watch your cpu activity while running the script with your file,
you will recognize that the script works as expected and doesn´t freeze.
But it takes really a long long time to finish all the calculations.
You might compare it to activating only a single selection tag and running the split command from the menu.
It takes disproportionately long to do such an operation with your geometry.The first and most important reason why this operation takes that long is that running the split command on a mesh with Ngons takes way much longer as on a triangulated version.
You might try running a triangulation command beforehand and run the script afterwards, you will recognize a dramatic speed improvement!
The second reason is python scripts aren´t multithreaded.
The third reason is the inefficiency of c4d´s built in split command.
Basically I guess the split command is implemented as a reverse delete command.
Internally the object is cloned, the selection inverted and afterwards deleted.(that´s my assumption during almost one month of testing and comparing, therefore no guaranteed information ;!Wink
[URL-REMOVED])
The advantage of this approach is that one doesn´t need to care too much about assigned tags, animations, etc.
But it lacks with dense meshes, low selection counts, randomized selections and if it e.g. comes to morph tags the built in split command won't handle
such a case appropriately.( I´m not quite sure if this is a bug or intended not to work)
All in all the problem is that there is no qualifier analyzing if it´s worth traversing all points, polygons and tags.
You might end up with traversing millions of points for separating just a single polygon.As you might have read in the linked post, I wrote a build up script that uses the opposite approach.
But it lacks if more than 33 % of the given polygons are selected, assuming that the selected items are in a row(e.g. indieces from 12 to 35).If the selection is more in a randomized manner the 33 % efficiency qualifier can be increased to almost 90%.
At the end I came up with an algorithm that reflects all necessary tags, animations etc.
and is much more efficient by using two qualifiers which analyze the selection at the beginning.
It decides if polyselection.GetCount()>= maxpolies/3 and if polyselection.GetSegments() is efficiently related to it.
If the qualifier is positive, it runs the build up approach. If it is negative, the deletion approach runs.
I hope you understand that I won't give this away for free(it was really a lot of work), but with all the information and the link to the other post you should be able to build such an algorithm which fits to your case perfectly.
You can pm me if you have further questions while writing it.But if you are fine with the triangulation method you can simply run the already provided script.
Best wishes
Martin
[URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.
-
On 23/07/2015 at 05:57, xxxxxxxx wrote:
thank you for the in-depth explanation!