3D Design

3D Design

Topics related to Ansys Discovery and Ansys SpaceClaim.

SpaceClaim Script: Selection by FilterByBoundingBox

    • ramiromena
      Subscriber

      Dear Ansys Learning Forum Community,

      I am trying to select a specific face in a geometry. The easiest way to do this task is by knowing in advance the index of the face of interest. However, this option lacks of scalability if my geometry is modified or generated in a different order. This solution is referred as Option 1.

      So, other option is to use the FilterByArea method. This works fine as long as your faces have a unique area, otherwise, you will select multiple faces instead of only one. This solution is referred as Option 2.

      Then, by searching the available options, there is the FilterByBoundingBox method where you can select a face that intersects with a previously defined box. This method looks as the most generic so that you can control the way a face is selected. However, due to the lack of documentation in SpaceClaim or the absence of a similar example, I am not able to use this method properly. Maybe is due to an error in the syntax or in my understanding of the method. Please, could you help me? This solution is referred as Option 3.

      Attached you will find a minimal working example (MWE) with the implementation of Option 1, 2 and 3. This last one is currently not working as is the one I am interested the most. Feel free to add/modify its content.

      However, if you know a better solution to select a specific face (i.e based on its normal or another feature, feel free to share your valuable know-how)

      As always, thank you for your help.

      Best regards,

      Ramiro

      #####
      """
      Minimal Working Example MWE
      Author: Ramiro MENA ANDRADE
      Date: 2023-06-12


      Script to generate a Cube of dimensions Cube_X, Cube_Y and Cube_Z
      and select faces based on three different methods:
          - Option1: When the index of the face is known in advance (not useful to fully automatize a code)
          - Option2: By using FilterByArea method (not useful if more than one face has the same area)
          - Option3: By using FilterByBoundingBox method (could be useful, but I do not know how to write the proper syntax)
      """

      # Python Script, API Version = V19
      #*************************************
      # Part 1: Geometry definition (dimensions in mm)
      #*************************************
      Cube_X= 10
      Cube_Y= 20
      Cube_Z= 5

      pointA = [0,0]
      pointB = [Cube_X,0]
      pointC = [Cube_X,Cube_Y]

      tol = 0.01 #define a tolerance
      area = Cube_X*Cube_Y #calculate the area

      #%%
      #*********************************
      #Part2: Geometry generation
      #*********************************
      sectionPlane = Plane.PlaneXY
      result = ViewHelper.SetSketchPlane(sectionPlane, None)
      # EndBlock

      # Set New Sketch
      result = SketchHelper.StartConstraintSketching()
      # EndBlock

      # Sketch Rectangle
      point1 = Point2D.Create(MM(pointA[0]),MM(pointA[1]))
      point2 = Point2D.Create(MM(pointB[0]),MM(pointB[1]))
      point3 = Point2D.Create(MM(pointC[0]),MM(pointC[1]))
      result = SketchRectangle.Create(point1, point2, point3)

      # Solidify Sketch
      mode = InteractionMode.Solid
      result = ViewHelper.SetViewMode(mode, None)
      # EndBlock

      # Extrude 1 Face
      selection = FaceSelection.Create(GetRootPart().Bodies[0].Faces[:])
      options = ExtrudeFaceOptions()
      options.ExtrudeType = ExtrudeType.Add
      result = ExtrudeFaces.Execute(selection, MM(Cube_Z), options)
      # EndBlock

      #%%
      #************************************************
      #Part 3: Selection of faces by different methods
      #*************************************************

      # OPTION 1: Create Named Selection Group (Top) 
      # PROBLEM: YOU NEED TO KNOW IN ADVANCE THE INDEX OF THE FACE
      primarySelection = FaceSelection.Create(GetRootPart().Bodies[0].Faces[0])
      secondarySelection = Selection.Empty()
      result = NamedSelection.Create(primarySelection, secondarySelection)
      result = NamedSelection.Rename("Group1", "Option1")
      # EndBlock


      #OPTION 2: Create a named selection by using FilterByArea
      #PROBLEM: FOR THIS CASE, MULTIPLE FACES CAN HAVE THE SAME AREA, SO YOU CAN NOT SELECT A SPECIFIC FACE
      comp = Selection.Create(GetRootPart())
      faces = comp.ConvertToFaces().FilterByArea(MM2(area-tol),MM2(area+tol))
      faces.CreateAGroup('Option2')

      #OPTION 3: Create a named selection by using FilterByBoundingBox Method
      #PROBLEM: I DO NOT KNOW THE PROPER SYNTAX FOR USING THIS METHOD CORRECTLY

      #Create Points 
      min_point = Point.Create(MM(pointA[0]), MM(pointA[1]), MM(0))
      max_point = Point.Create(MM(pointC[0]), MM(pointC[1]), MM(0))

      #Create a Box
      mbox = Box.Create(min_point, max_point)

      #Apply the Filter to a face (fface means filtered face)
      fface = comp.ConvertToFaces().FilterByBoundingBox(mbox)
      fface.CreateAGroup('Option3')

    • Aniket
      Forum Moderator

      Hi Ramiro,

      First of all very well-written question! Kudos for that! There was an issue in older APIs of FilterByBoundingBox which is fixed in 2023 R1.

      so something, as follows, would work in 2023R1:

      from SpaceClaim.Api.V23 import *
      PartSel = Selection.Create(GetRootPart())
      faces = PartSel.ConvertToFaces()
      BoundingBox = Box.Create(MM(-30),MM(-30),MM(-30),MM(30),MM(30),MM(30))
      facesInBoundingBox = faces.FilterByBoundingBox(BoundingBox)

      You may want to upgrade to 2023R1.

      If that's not possible, possibly you can loop through faces and check their centroid such as:

      GetRootPart().Bodies[0].Faces[0].EvalMid().Point

      -Aniket

      How to access Ansys help links

      Guidelines for Posting on Ansys Learning Forum

    • ramiromena
      Subscriber

      Hi Aniket.

      Thank you for your positive feedback and for your quick reply. Currently I do not have the 2023R1 version, but I am glad to know that there is a solution in the future version. In the meantime, the hint of using the centroid is super useful.

      I will proceed to update my script and kudos for you too :).

      Cheers,

      Ramiro

    • christian.scheffler
      Subscriber

      Hi Aniket,

      are you sure the bug in the FilterByBoundingBox() and FilterByBoundingSphere() method is already fixed in V23 version (ANSYS 2023 R1)?
      Could anybody test it?

      My experience with V23: Neither of these functions is working in my script :( 
      It seems that it does not create a subset of the total set, although I thoroughly checked the parameters.

      Cheers,
      Christian

      • Aniket
        Forum Moderator

        That wont work as is but following seems to working:

        PartSel = Selection.Create(GetRootPart())
        Faces = PartSel.ConvertToFaces()
        BoundingBox = Box.Create(MM(-30),MM(-30),MM(-30),MM(30),MM(30),MM(30))
        FacesInBoundingBox = Faces.FilterByBoundingBox(BoundingBox)

        -Aniket

        Forum Rules & Guidelines

    • christian.scheffler
      Subscriber

       

       

      Hi Aniket,

      unfortunately the FilterByBoundingBox method is not working for me in V23. But I agree with you, the x, y, z order is correct for your example above.

      public static Box Create(
      	double minX,
      	double minY,
      	double minZ,
      	double maxX,
      	double maxY,
      	double maxZ
      )

      Please find a MWE below.
      Probelm: In my case this does not limit the total set to the subset of faces.

      Best regards
      Christian

      ###

       

      # Python Script, API Version = V23
      #*************************************
      # Geometry definition (dimensions in mm)
      #*************************************

      width= 2
      length= 100
      number_of_arms = 3


      #*********************************
      #Part2: Geometry generation
      #*********************************

      # 3 Arms

      # Set Sketch Plane
      sectionPlane = Plane.PlaneXY
      result = ViewHelper.SetSketchPlane(sectionPlane, None)
      # EndBlock

      # Sketch Rectangle
      point1 = Point2D.Create(MM(width/2),MM(0))
      point2 = Point2D.Create(MM(-width/2),MM(0))
      point3 = Point2D.Create(MM(-width/2),MM(length))
      result = SketchRectangle.Create(point1, point2, point3)
      # EndBlock

      # Solidify Sketch
      mode = InteractionMode.Solid
      result = ViewHelper.SetViewMode(mode, Info4)
      # EndBlock

      # Rotieren über Z-Griff
      selection = BodySelection.Create(GetRootPart().Bodies[:])
      anchor = CoordinateSystem1
      axis = Move.GetAxis(anchor)
      options = MoveOptions()
      options.CreatePatterns = True
      angle=360/number_of_arms
      result = Move.Rotate(selection, axis, DEG(angle), options, Info13)
      # EndBlock

      # Circle

      # Set Sketch Plane
      sectionPlane = Plane.PlaneXY
      result = ViewHelper.SetSketchPlane(sectionPlane, Info6)
      # EndBlock

      # Sketch Circle
      origin = Point2D.Create(0,0)
      result = SketchCircle.Create(origin, MM(10))
      # EndBlock

      # Solidify Sketch
      mode = InteractionMode.Solid
      result = ViewHelper.SetViewMode(mode, Info7)
      # EndBlock

      # Copy Elements out of Components (Pattern)
      selection = BodySelection.Create(GetRootPart().Components[0].Components[0].Content.Bodies[0])
      result = Copy.Execute(selection)
      selection = BodySelection.Create(GetRootPart().Components[0].Components[1].Content.Bodies[0])
      result = Copy.Execute(selection)
      selection = BodySelection.Create(GetRootPart().Components[0].Components[2].Content.Bodies[0])
      result = Copy.Execute(selection)
      # EndBlock

      # Delete Objects (Components)
      selection = ComponentSelection.Create(GetRootPart().Components[:])
      result = Delete.Execute(selection)
      # EndBlock

      # Rename
      GetRootPart().Bodies[0].SetName("Circle")
      GetRootPart().Bodies[1].SetName("Arm1")
      GetRootPart().Bodies[2].SetName("Arm2")
      GetRootPart().Bodies[3].SetName("Arm3")
      # EndBlock


      # Project to solid
      selection = FaceSelection.Create(GetRootPart().Bodies[0].Faces[:])
      target = FaceSelection.Create(GetRootPart().Bodies[1].Faces[:])
      direction = Selection.Create(GetRootPart())
      result = ProjectToSolid.Execute(selection, target, direction)
      # EndBlock

      # Project to solid
      selection = FaceSelection.Create(GetRootPart().Bodies[0].Faces[:])
      target = FaceSelection.Create(GetRootPart().Bodies[2].Faces[:])
      direction = Selection.Create(GetRootPart())
      result = ProjectToSolid.Execute(selection, target, direction)
      # EndBlock

      # Project to solid
      selection = FaceSelection.Create(GetRootPart().Bodies[0].Faces[:])
      target = FaceSelection.Create(GetRootPart().Bodies[3].Faces[:])
      direction = Selection.Create(GetRootPart())
      result = ProjectToSolid.Execute(selection, target, direction)
      # EndBlock


      #************************************************
      #Part 3: Selection of faces by different methods
      #*************************************************

      PartSel1 = Selection.Create(GetRootPart())
      Faces1 = PartSel1.ConvertToFaces()
      PartSel2 = Selection.Create(GetRootPart().Bodies[0])
      Faces2 = PartSel2.ConvertToFaces()
      Faces = Selection.Difference(Faces1,Faces2)
      BoundingBox = Box.Create(MM(-20),MM(-20),MM(-2),MM(20),MM(20),MM(2))
      FacesInBoundingBox = Faces.FilterByBoundingBox(BoundingBox)

      # FacesInBoundingBox contains all the faces of the 3 arms.
      # Expected was a selection of the 3 faces underneath the circle ONLY
      result = Delete.Execute(FacesInBoundingBox)

       

    • Aniket
      Forum Moderator

      Hi Christian,

      Ansys employees can not run the codes they get on the forum, but I would recommend you to take the snippet that I shared and create some bodies randomly in your model and see if the bounding box method works, please note it will also select the faces if they are partially inside the bounding box.

      image

       

    • christian.scheffler
      Subscriber

      Hi Ankit, 

      thanks! The problem was that my bounding box intersects the outer areas which I didn’t want to be selected. That’s what I have overlooked in the method description.
      A size reduction of bounding box helps in this case! 

      Problem solved for versions >= ANSYS 2023R1 (v23)

Viewing 6 reply threads
  • The topic ‘SpaceClaim Script: Selection by FilterByBoundingBox’ is closed to new replies.