fetching geometry/Toolpath for svg paths

xenia.pie
Explorer

fetching geometry/Toolpath for svg paths

xenia.pie
Explorer
Explorer

Hi there,

 

I am struggling to find a generic script to extract the outer and inner (holes, pockets, etc) geometry from the up & down faces of my 3D models.

 

So, the starting point is to identify the parts of my model that are sheet-goods and identify the up & down faces, so the shortest distance between these faces determines the thickness of the part. With the faces identified, I get the face.loops and iterate them through the edges. If edges.count == 1 -> circle or ellipse. If edges.count > 1, then it's a mix between lines and arcs, and here is where I'm struggling.

 

the process goes: Iterate through the loops on faces, identify the coEdges and egdes and determine if the edge is isOpposedToEdge or isParamReversed  plus check the edge.evaluator.getEndPoints() (start and end points) makes sense respective the previous edge: (see snippet of code below)

                path = ""
                start = None
                end = None
                c = 0

                for coEdge in loop.coEdges:
                    reversed = False
                    edge = coEdge.edge
                    curve_type = edge.geometry.curveType
                    # determine if edge is reversed
                    isOpposedToEdge = coEdge.isOpposedToEdge
                    isParamReversed = coEdge.isParamReversed

                    (returnBool, startPoint, endPoint) = edge.evaluator.getEndPoints()

                    if self.getTwoD(u, v, endPoint) == end:
                        reversed = True
                    if self.getTwoD(u, v, startPoint) == start:
                        print('this is wrong')
                    start = self.getTwoD(u, v, startPoint)
                    end = self.getTwoD(u, v, endPoint)
                    

                    if c == 0:
                        if coEdge.isOpposedToEdge and coEdge.isParamReversed:
                            path = f"M {end[0]} {end[1]}  "
                            path += self.getLineArcPath(start, edge, face, isParamReversed, isOpposedToEdge)
                        
                        else: 
                            path = f'M {start[0]} {start[1]}  '
                            path += self.getLineArcPath(end, edge, face, isParamReversed, isOpposedToEdge)
                        c += 1
                        print(path)
                    else:
                        if coEdge.isOpposedToEdge and coEdge.isParamReversed or reversed:
                            path += self.getLineArcPath(start, edge, face, isParamReversed, isOpposedToEdge)
                            start,end = end,start
                        else:
                            path += self.getLineArcPath(end, edge, face, isParamReversed, isOpposedToEdge)
                        c += 1
               path += "Z"

identify if edge is either Line or Arc:

def getLineArcPath(self, end, edge, face, isParamReversed, isOpposedToEdge):
        curve_type = edge.geometry.curveType
        # line segment:
        if curve_type == 0:
            path = f"L {end[0]} {end[1]}  "
            print(path)
        # arc:
        elif curve_type == 1:
            
            face_normal = face.geometry.normal
            arc_normal = edge.geometry.normal
            opp_or_equal = self.check_vectors(face_normal,arc_normal)
            arc = edge.geometry
            rx = str(arc.radius)
            ry = str(arc.radius)
            rotation = "0"
            large_arc_flag = "0"
            sweep_flag = "0"

            angle = abs(arc.endAngle - arc.startAngle)
            if angle >= 3.141592653589793 :
                large_arc_flag = "1"
          
            if isParamReversed ==  True and isOpposedToEdge == True and opp_or_equal == 'opposite':
                sweep_flag = "1"
            if isParamReversed ==  False and isOpposedToEdge == False and opp_or_equal == 'equal':
                sweep_flag = "1"
   
            x = str(end[0])
            y = str(end[1])

            path =f"A {rx} {ry} {rotation} {large_arc_flag} {sweep_flag} {x} {y} "
            print(path)

        return path

To determine the sweep_flag and the large_arc_flag of the arcs, I use this function:

def check_vectors(self,face_normal,arc_normal):
        """Checks face normal vector and arc normal vector angle.
        They can be opposites or parallels.

        Args:
            face_normal ([3D vector]): fusion builtin type
            arc_normal ([3D vector]): fusion builtin type

        Returns:
            [string]: whether are equal or opposites
        """
        if arc_normal.angleTo(face_normal) == math.pi:
            # print('opposite')
            return 'opposite'
        elif arc_normal.angleTo(face_normal) == 0:
            # print('equal')
            return 'equal'
        else:
            return 'error'

 

This works fine for some models, but for some others won't and I'm not sure why..

(some examples attached in this post. Same code used in both cases, but geometry is wrong on the table file for some arcs.)
The main questions are regarding how to make sure the arcs are defined properly and also which property should I use to check if segment is reversed and so flip them accordingly. But if someone knows how to get a consistent geometry loops, then I would really appreciate it!

Thank you!


 

0 Likes
Reply
437 Views
1 Reply
Reply (1)

BrianEkins
Mentor
Mentor

I have two thoughts.

 

First, handling arcs can sometimes be tricky, and rather than figure out the correct sweep direction and angles it might be easier to get the endpoints and a midpoint and create an arc in your data based on that.

 

Second, have you tried the Shaper Utilities app from the Autodesk App Store? It's free and possibly already does what you're trying to do.

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes