Detect triangles on the Subd. Wish

Hello.
Is there any way to analysis subd object for the presence of triangles/pentagons?
Just like it was in T-Splines оr another method.



This is !_tsLayout in T-Splines.

import Rhino
import scriptcontext

def mark_subd():
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select SubD")
    go.GeometryFilter = Rhino.DocObjects.ObjectType.SubD
    go.SubObjectSelect = False
    go.GroupSelect = True
    go.DeselectAllBeforePostSelect = False
    go.OneByOnePostSelect = True
    go.GetMultiple(1, 0)
    if go.CommandResult() != Rhino.Commands.Result.Success:
        return go.CommandResult()
    for i in range(go.ObjectCount):
        objref = go.Object(i)
        obj = objref.Object()
        if not obj: continue
        subd = objref.SubD()
        if not subd: continue
        guids = []
        for face in subd.Faces:
            if face.EdgeCount not in [3, 5]: continue
            guid = scriptcontext.doc.Objects.AddTextDot(str(face.EdgeCount), face.LimitSurfaceCenterPoint)
            guids.append(guid)
        index = scriptcontext.doc.Groups.Add(guids)
    scriptcontext.doc.Views.Redraw()

if __name__=="__main__":
    mark_subd()

mark_subd.py (1016 Bytes)

4 Likes

Hi Mahdiyar.
Works great, thanks very much!

Could I ask to make a preselection?

I’m trying to assign the code for the toolbar button.
But for some reason the script does not work.

! _-RunPythonScript
(
import Rhino
import scriptcontext

def mark_subd():
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select SubD")
    go.GeometryFilter = Rhino.DocObjects.ObjectType.SubD
    go.SubObjectSelect = False
    go.GroupSelect = True
    go.DeselectAllBeforePostSelect = False
    go.OneByOnePostSelect = True
    go.GetMultiple(1, 0)
    if go.CommandResult() != Rhino.Commands.Result.Success:
        return go.CommandResult()
    for i in range(go.ObjectCount):
        objref = go.Object(i)
        obj = objref.Object()
        if not obj: continue
        subd = objref.SubD()
        if not subd: continue
        guids = []
        for face in subd.Faces:
            if face.EdgeCount not in [3, 5]: continue
            guid = scriptcontext.doc.Objects.AddTextDot(str(face.EdgeCount), face.LimitSurfaceCenterPoint)
            guids.append(guid)
        index = scriptcontext.doc.Groups.Add(guids)
    scriptcontext.doc.Views.Redraw()

if __name__=="__main__":
    mark_subd()

)

Rhino 7

I changed the script a little so that it is run with the selected object. But after script execution the model remains selected.
I would like to imitate the command _SelNone inside the Python. As far as I understand, the rs.UnselectAllObjects() is responsible for this.
I tried to use it in different variations, but the objects remains selected.


import Rhino
import scriptcontext
import rhinoscriptsyntax as rs
import scriptcontext as sc



def mark_subd():
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select SubD")
    go.GeometryFilter = Rhino.DocObjects.ObjectType.SubD
    go.SubObjectSelect = False
    go.GroupSelect = True
    go.GetMultiple(1, 0)
    
    
    if go.CommandResult() != Rhino.Commands.Result.Success:
        return go.CommandResult() 
        rs.UnselectAllObjects()
    for i in range(go.ObjectCount):
        objref = go.Object(i)
        obj = objref.Object()
        if not obj: continue
        subd = objref.SubD()
        if not subd: continue
        guids = []
        for face in subd.Faces:
            if face.EdgeCount not in [3, 5]: continue
            guid = scriptcontext.doc.Objects.AddTextDot(str(face.EdgeCount), face.LimitSurfaceCenterPoint)
            guids.append(guid)
        index = scriptcontext.doc.Groups.Add(guids)
    scriptcontext.doc.Views.Redraw()

if __name__=="__main__":
    mark_subd()

I managed to remove the selected after the script completes with macro.
It works well enough, but if the models do not contain triangles or pentagons, then confusion occurs. Objects selected not the right one, and are coloured in red. :lying_face:

import Rhino
import scriptcontext
import rhinoscriptsyntax as rs
import scriptcontext as sc



def mark_subd():
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select SubD")
    go.GeometryFilter = Rhino.DocObjects.ObjectType.SubD
    go.SubObjectSelect = False
    go.GroupSelect = True
    go.GetMultiple(1, 0)
    
    
    if go.CommandResult() != Rhino.Commands.Result.Success:
        return go.CommandResult() 
        rs.UnselectAllObjects()
    
    
    for i in range(go.ObjectCount):
        objref = go.Object(i)
        obj = objref.Object()
        if not obj: continue
        subd = objref.SubD()
        if not subd: continue
        guids = []
        for face in subd.Faces:
            if face.EdgeCount not in [3, 5,]: continue
            guid = scriptcontext.doc.Objects.AddTextDot(str(face.EdgeCount), face.LimitSurfaceCenterPoint)
            guids.append(guid)
        index = scriptcontext.doc.Groups.Add(guids)
    scriptcontext.doc.Views.Redraw()

if __name__=="__main__":
    mark_subd()


    rs.Command('_SelNone _SelLast -Properties _Pause _Object _Color _Object 255,0,0 _EnterEnd')  
    rs.Command('_SelNone')
import Rhino
import scriptcontext

def mark_subd():
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select SubD")
    go.GeometryFilter = Rhino.DocObjects.ObjectType.SubD
    go.SubObjectSelect = False
    go.GroupSelect = True
    go.GetMultiple(1, 0)
    if go.CommandResult() != Rhino.Commands.Result.Success:
        return go.CommandResult()
    for i in range(go.ObjectCount):
        objref = go.Object(i)
        obj = objref.Object()
        obj.Select(False)
        if not obj: continue
        subd = objref.SubD()
        if not subd: continue
        ids = []
        for face in subd.Faces:
            if face.EdgeCount not in [3, 5]: continue
            id = scriptcontext.doc.Objects.AddTextDot(str(face.EdgeCount), face.LimitSurfaceCenterPoint)
            ids.append(id)
        index = scriptcontext.doc.Groups.Add(ids)
    scriptcontext.doc.Views.Redraw()

if __name__=="__main__":
    mark_subd()

mark_subd.py (965 Bytes)

Many thanks for the help, Mahdiyar.

I would like to get colored dots to faster looking for areas with improper geometry. Ideally, it would be possible to get two colors in one script, for example red for triangles, and orange for pentagons.

I’m trying to improve the script on my own. I did not find suitable examples on the forum, but found in the documentation an example with the sphere, and added it to the script in different versions.

  attributes = ObjectAttributes()
  attributes.ObjectColor = Color.FromArgb(255, 127, 0)
  attributes.ColorSource = ObjectColorSource.ColorFromObject

I added "attributes" to the line:
id = scriptcontext.doc.Objects.AddTextDot(str(face.EdgeCount), face.LimitSurfaceCenterPoint, attributes)

But I constantly get a mistake. Script does not work.

Of course I can stay with macro, but it does not always work correctly. And If I use _SelDot , then all the dots that are in the scene are affected.

import Rhino
import scriptcontext
from System.Drawing import Color

def mark_subd():
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select SubD")
    go.GeometryFilter = Rhino.DocObjects.ObjectType.SubD
    go.SubObjectSelect = False
    go.GroupSelect = True
    go.GetMultiple(1, 0)
    if go.CommandResult() != Rhino.Commands.Result.Success:
        return go.CommandResult()
    att = Rhino.DocObjects.ObjectAttributes()
    att.ObjectColor = Color.FromArgb(255, 127, 0)
    att.ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject
    for i in range(go.ObjectCount):
        objref = go.Object(i)
        obj = objref.Object()
        obj.Select(False)
        if not obj: continue
        subd = objref.SubD()
        if not subd: continue
        ids = []
        for face in subd.Faces:
            if face.EdgeCount not in [3, 5]: continue
            id = scriptcontext.doc.Objects.AddTextDot(str(face.EdgeCount), face.LimitSurfaceCenterPoint, att)
            ids.append(id)
        index = scriptcontext.doc.Groups.Add(ids)
    scriptcontext.doc.Views.Redraw()

if __name__=="__main__":
    mark_subd()

mark_subd.py (1.1 KB)

2 Likes

Hi Mahdiyar.
Thank you very much for your script, it works great!

But I decided to improve it a little.
The script searches for the triangles and pentagons separately, and mark the elements in different colors.
I wrote is not as very elegant as you, because I am not a programmer. But it works as it should!
I hope that other members will find it useful for them.

Once again, I thank you for your help! :handshake:




import Rhino
import scriptcontext
from System.Drawing import Color

def mark_subd():
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select SubD")
    go.GeometryFilter = Rhino.DocObjects.ObjectType.SubD
    go.SubObjectSelect = False
    go.GroupSelect = True
    go.GetMultiple(1, 0)
    if go.CommandResult() != Rhino.Commands.Result.Success:
        return go.CommandResult()
    att3 = Rhino.DocObjects.ObjectAttributes()
    att3.ObjectColor = Color.GreenYellow
    att3.ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject
    
    att5 = Rhino.DocObjects.ObjectAttributes()
    att5.ObjectColor = Color.OrangeRed
    att5.ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject
    
    for i in range(go.ObjectCount):
        objref = go.Object(i)
        obj = objref.Object()
        obj.Select(False)
        if not obj: continue
        subd = objref.SubD()
        if not subd: continue
        ids = []
        for face in subd.Faces:
            if face.EdgeCount not in [3]: continue
            id = scriptcontext.doc.Objects.AddTextDot(str(face.EdgeCount), face.LimitSurfaceCenterPoint, att3)
            ids.append(id)
            
    for i in range(go.ObjectCount):
        objref = go.Object(i)
        obj = objref.Object()
        obj.Select(False)
        if not obj: continue
        subd = objref.SubD()
        if not subd: continue

        for face in subd.Faces:
            if face.EdgeCount not in [5]: continue
            id = scriptcontext.doc.Objects.AddTextDot(str(face.EdgeCount), face.LimitSurfaceCenterPoint, att5)
            ids.append(id)

        index = scriptcontext.doc.Groups.Add(ids)
    scriptcontext.doc.Views.Redraw()

if __name__=="__main__":
    mark_subd()


1 Like