How can I convert coordinates from global to local CS in Mechanical?

Pierre Thieffry
Pierre Thieffry Member, Moderator, Employee Posts: 107
25 Answers Second Anniversary 10 Comments 25 Likes
✭✭✭✭

When I select an entity in Mechanical, I can choose a coordinate system to display coordinates in the selection information. Is there a way to do it by script?

Answers

  • Pierre Thieffry
    Pierre Thieffry Member, Moderator, Employee Posts: 107
    25 Answers Second Anniversary 10 Comments 25 Likes
    ✭✭✭✭
    edited November 2023

    Here's an example for converting coordinates to a local coordinate system. Pay attention to proper unit conversions. The example works on cartesian coordinate systems and would require little work to apply to cylindrical CS as well.

    def convertToCS(coords,cs_name,convert=True):
        # Converts coordinates to a given coordinate system
        # If convert=True, 'coords' is assumed to be in users unit
        # If convert=False, 'coords' must be in meters
        import units
    
        # Retrieve conversion factor from current length unit to meters
        toUnit = "m" # Always generate the result to display in SI unit
        fromUnit=ExtAPI.DataModel.AnalysisList[0].CurrentConsistentUnitFromQuantityName("Length")
        convFact = units.ConvertUnit(1, fromUnit, toUnit, "Length")
    
        # Retrieve axis from coordinate system
        # Assume cs_name is unique (if not, the first one will be used)
        csM = ExtAPI.DataModel.GetObjectsByName(cs_name)[0]
        csXAxis = csM.XAxis
        csYAxis = csM.YAxis
        csZAxis = csM.ZAxis
    
        # Convert to 3D vectors
        xAxis = Vector3D(csXAxis[0], csXAxis[1], csXAxis[2])
        yAxis = Vector3D(csYAxis[0], csYAxis[1], csYAxis[2])
        zAxis = Vector3D(csZAxis[0], csZAxis[1], csZAxis[2])
    
        # create transformation matrix
        # We use a 4x4 matrix with rotation and translations
        idM  =  Matrix4D()
        transM = idM.CreateSystem(xAxis,yAxis,zAxis)
        # Transpose to ensure proper transformation from global to local
        transM.Transpose()
    
        # Translation part of the transformation matrix
        origin=csM.Origin # Origin will be in user units, so convert to m
        origin_transfd=transM.Transform(Vector3D(origin[0],origin[1],origin[2]))
    
        for i in range(0,3):
            transM[12+i]=-origin_transfd[i]
    
        # Now convert point to new CS
        # First convert to meters if needed
        if convert:
            vec=Vector3D(coords[0]*convFact, coords[1]*convFact, coords[2]*convFact)
        else:
            vec=Vector3D(coords[0], coords[1], coords[2])
    
        # Rotate
        vec_transfd=transM.Transform(vec)
    
        # Return new coordinates in user units
        if convert:
            invFact=1/convFact
            return [vec_transfd[0]*invFact,vec_transfd[1]*invFact,vec_transfd[2]*invFact]
        else:
            return [vec_transfd[0],vec_transfd[1],vec_transfd[2]]
    
    # Test function on current selection's centroid 
    cursel=ExtAPI.SelectionManager.CurrentSelection
    # using convert=False in function call as Centroid is always in meters
    print(convertToCS(cursel.Entities[0].Centroid,'myCS',False)) 
    
  • Landon Mitchell Kanner
    Landon Mitchell Kanner Member, Employee Posts: 295
    25 Answers 100 Comments Second Anniversary 25 Likes
    ✭✭✭✭

    Here are some similarly useful functions.

  • ZZ.tang
    ZZ.tang Member Posts: 17
    Name Dropper First Comment
    **

    When I try to run this function, it seems return a wrong result.
    when I made some modification. Then it works (only tested for Mechanical unit in "mm")
    I'm not sure is that a correct modification?
    And, is .Centroid always return in "m"?

    convFact = units.ConvertUnit(1, fromUnit, toUnit, "Length")
    

    to

    convFact = units.ConvertUnit(1, toUnit, fromUnit, "Length")
    
    

    and

    if convert:
       invFact=1/convFact
    

    to

        if not convert:
    
  • Landon Mitchell Kanner
    Landon Mitchell Kanner Member, Employee Posts: 295
    25 Answers 100 Comments Second Anniversary 25 Likes
    ✭✭✭✭

    I believe .Centroid uses this unit:
    ExtAPI.Graphics.Unit

  • ZZ.tang
    ZZ.tang Member Posts: 17
    Name Dropper First Comment
    **

    @Landon Mitchell Kanner said:
    I believe .Centroid uses this unit:
    ExtAPI.Graphics.Unit

    I checked ExtAPI.Graphics.Unit, it seems the value was not changed with the mechanical unit setting or graphics. So, what is this value really is?

    And which value will change with the mechanical unit setting?

  • Pierre Thieffry
    Pierre Thieffry Member, Moderator, Employee Posts: 107
    25 Answers Second Anniversary 10 Comments 25 Likes
    ✭✭✭✭

    @ZZ.tang the internal geometry is I believe always in m and ExtAPI.Graphics.Unit is there constant to "m".

    If you want to grab the current user unit, you can use this:

    lunit=DataModel.CurrentUnitFromQuantityName("Length")

  • Landon Mitchell Kanner
    Landon Mitchell Kanner Member, Employee Posts: 295
    25 Answers 100 Comments Second Anniversary 25 Likes
    ✭✭✭✭
    edited December 2023

    ExtAPI.Graphics.Unit is the internal geometry units, which depends on the CAD file and how you imported it. It is usually meters but not always. This is the unit for face.Centroid that you asked about.

    You can view this unit under Geometry > Definition > Length Unit:

    @Pierre Thieffry , You may need to update your code for the case where Centroid unit is not meters. Test file is attached.

  • Mike.Thompson
    Mike.Thompson Member, Employee Posts: 342
    25 Answers 100 Comments 25 Likes First Anniversary
    ✭✭✭✭
    edited December 2023

    @Pierre Thieffry @ZZ.tang ,
    I think there are CAD imports that can effect the unit of the geometry. To get this unit for the geometry (GeoData) you can use this:

    ExtAPI.DataModel.GeoData.Unit

    https://discuss.ansys.com/discussion/2791

  • Landon Mitchell Kanner
    Landon Mitchell Kanner Member, Employee Posts: 295
    25 Answers 100 Comments Second Anniversary 25 Likes
    ✭✭✭✭

    Hmmm. I forgot about ExtAPI.DataModel.GeoData.Unit. Anyone know the difference between ExtAPI.DataModel.GeoData.Unit and ExtAPI.Graphics.Unit? In my testing, it seems that they are both always equal to Geometry > Definition > Length Unit

  • Mike.Thompson
    Mike.Thompson Member, Employee Posts: 342
    25 Answers 100 Comments 25 Likes First Anniversary
    ✭✭✭✭

    @Landon Mitchell Kanner , I think the current setup in Mechanical is the Graphics unit will be the same as the CAD unit, but no guarantee this could not change in the future. The fact that each domain has the capacity for its own unit is robustness in the Mechanical API, and thus it would be best practice to obtain the unit in whichever domain you are working in and ensure consistency with others by way of built-in unit conversions.