コード例 #1
0
 def __init__(self, drawingView, calculateBounds=False ):
     self.name = drawingView.Name
     #self.scale =  drawingView.Scale #not always correct for center line objects.
     self.drawing_x = drawingView.X
     self.drawing_y = drawingView.Y
     self.viewResult_length = len(drawingView.ViewResult)
     self.viewResult_hash = hash(drawingView.ViewResult)
     if calculateBounds:
         XML_tree = SvgXMLTreeNode(drawingView.ViewResult, 0)
         scaling = XML_tree.scaling()
         self.scale = scaling
         for element in XML_tree.getAllElements():
             if element.tag == 'circle':
                 x, y = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
                 r =  float( element.parms['r'] )* scaling
                 self.updateBounds_ellipse( x, y, r, r )
             if element.tag == 'ellipse':
                 cx, cy = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
                 rx, ry = float( element.parms['rx'] )* scaling, float( element.parms['ry'] )* scaling
                 self.updateBounds_ellipse( cx, cy, rx, ry )
             if element.tag == 'path': 
                 path = SvgPath( element )
                 for p in path.points:
                     self.updateBounds( p.x, p.y )
             if element.tag == 'line':
                 x1, y1 = element.applyTransforms( float( element.parms['x1'] ), float( element.parms['y1'] ) )
                 x2, y2 = element.applyTransforms( float( element.parms['x2'] ), float( element.parms['y2'] ) )
                 self.updateBounds( x1, y1 )
                 self.updateBounds( x1, y2 )
コード例 #2
0
def getPoints(svg):
    "returns a series of (x,y) points from an SVG fragment"
    # adapted from selectionOverlay.py
    points = []
    XML_tree = SvgXMLTreeNode(svg, 0)
    scaling = XML_tree.scaling()
    SelectViewObjectPoint_loc = None
    for element in XML_tree.getAllElements():
        if element.tag == 'circle':
            x, y = element.applyTransforms(float(element.parms['cx']),
                                           float(element.parms['cy']))
            points.append((x, y))
        elif element.tag == 'ellipse':
            x, y = element.applyTransforms(float(element.parms['cx']),
                                           float(element.parms['cy']))
            points.append((x, y))
        elif element.tag == 'text' and element.parms.has_key('x'):
            x, y = element.applyTransforms(float(element.parms['x']),
                                           float(element.parms['y']))
            points.append((x, y))
        elif element.tag == 'path':
            path = SvgPath(element)
            for p in path.points:
                points.append((p.x, p.y))
        elif element.tag == 'line':
            x1, y1 = element.applyTransforms(float(element.parms['x1']),
                                             float(element.parms['y1']))
            x2, y2 = element.applyTransforms(float(element.parms['x2']),
                                             float(element.parms['y2']))
            points.append((x1, y1))
            points.append((x2, y2))
    return points
コード例 #3
0
 def __init__(self, drawingView, calculateBounds=False ):
     self.name = drawingView.Name
     #self.scale =  drawingView.Scale #not always correct for center line objects.
     self.drawing_x = drawingView.X
     self.drawing_y = drawingView.Y
     self.viewResult_length = len(drawingView.ViewResult)
     self.viewResult_hash = hash(drawingView.ViewResult)
     if calculateBounds:
         XML_tree = SvgXMLTreeNode(drawingView.ViewResult, 0)
         scaling = XML_tree.scaling()
         self.scale = scaling
         for element in XML_tree.getAllElements():
             if element.tag == 'circle':
                 x, y = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
                 r =  float( element.parms['r'] )* scaling
                 self.updateBounds_ellipse( x, y, r, r )
             if element.tag == 'ellipse':
                 cx, cy = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
                 rx, ry = float( element.parms['rx'] )* scaling, float( element.parms['ry'] )* scaling
                 self.updateBounds_ellipse( cx, cy, rx, ry )
             if element.tag == 'path': 
                 path = SvgPath( element )
                 for p in path.points:
                     self.updateBounds( p.x, p.y )
             if element.tag == 'line':
                 x1, y1 = element.applyTransforms( float( element.parms['x1'] ), float( element.parms['y1'] ) )
                 x2, y2 = element.applyTransforms( float( element.parms['x2'] ), float( element.parms['y2'] ) )
                 self.updateBounds( x1, y1 )
                 self.updateBounds( x1, y2 )
コード例 #4
0
def getPoints(svg):
    "returns a series of (x,y) points from an SVG fragment"
    # adapted from selectionOverlay.py
    points = []
    XML_tree =  SvgXMLTreeNode(svg,0)
    scaling = XML_tree.scaling()
    SelectViewObjectPoint_loc = None
    for element in XML_tree.getAllElements():
        if element.tag == 'circle':
            x, y = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
            points.append((x,y))
        elif element.tag == 'ellipse':
            x, y = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
            points.append((x,y))
        elif element.tag == 'text' and element.parms.has_key('x'):
            x, y = element.applyTransforms( float( element.parms['x'] ), float( element.parms['y'] ) )
            points.append((x,y))
        elif element.tag == 'path': 
            path = SvgPath( element )
            for p in path.points:
                points.append((p.x, p.y))
        elif element.tag == 'line':
            x1, y1 = element.applyTransforms( float( element.parms['x1'] ), float( element.parms['y1'] ) )
            x2, y2 = element.applyTransforms( float( element.parms['x2'] ), float( element.parms['y2'] ) )
            points.append((x1, y1))
            points.append((x2, y2))
    return points
コード例 #5
0
 def __init__(self, SvgXML, element_tag_of_interest, doFittedCircles=False):
     'parses a SVG and returns a FreeCAD_Object.Shape styled data structure'
     self.points = []
     self.lines = []
     self.circles = []
     self.ellipses = []
     self.arcs = []
     self.texts = []
     XML_tree =  SvgXMLTreeNode( SvgXML, 0 )
     scaling = XML_tree.scaling()
     for element in XML_tree.getAllElements():
         if element.tag != element_tag_of_interest:
             continue
         if element.tag == 'circle':
             x, y = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
             r =  float( element.parms['r'] )* scaling
             self.circles.append( [ x, y, r] )
             self.ellipse_points( x, y, r, r )
         if element.tag == 'ellipse': #no angle parm?
             cx, cy = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
             rx, ry = float( element.parms['rx'] )* scaling, float( element.parms['ry'] )* scaling
             self.ellipses.append( [ cx, cy, rx, ry] )
             self.ellipse_points( cx, cy, rx, ry )
         if element.tag == 'text' and element.parms.has_key('x'):
             x, y = element.applyTransforms( float( element.parms['x'] ), float( element.parms['y'] ) )
             self.texts.append( [x, y, element] )
         if element.tag == 'path': 
             path = SvgPath( element )
             for p in path.points:
                 self.points.append( [p.x, p.y] )
             for line in path.lines:
                 self.lines.append([ line.x1, line.y1, line.x2, line.y2 ])
                 self.points.append( line.midPoint() )
             for arc in path.arcs:
                 if arc.circular:
                     self.circles.append( [arc.center[0], arc.center[1], arc.r*scaling] )
                 else:
                     self.ellipses.append( [arc.center[0], arc.center[1], arc.rX*scaling, arc.rY*scaling ] )
                 self.points.append( [arc.center[0], arc.center[1]] )
             if doFittedCircles:
                 for bezierCurve in path.bezierCurves:
                     x, y, r, r_error = bezierCurve.fitCircle()
                     if r_error < 10**-4:
                         self.circles.append( [ x, y, r] )
         if element.tag == 'line':
             x1, y1 = element.applyTransforms( float( element.parms['x1'] ), float( element.parms['y1'] ) )
             x2, y2 = element.applyTransforms( float( element.parms['x2'] ), float( element.parms['y2'] ) )
             self.points.append( [x1, y1] )
             self.points.append( [x2, y2] )
             self.points.append( [(x1+x2)/2, (y1+y2)/2] )
             self.lines.append(  [x1, y1, x2, y2 ] )
コード例 #6
0
 def __init__(self, SvgXML, element_tag_of_interest, doFittedCircles=False):
     'parses a SVG and returns a FreeCAD_Object.Shape styled data structure'
     self.points = []
     self.lines = []
     self.circles = []
     self.ellipses = []
     self.arcs = []
     self.texts = []
     XML_tree =  SvgXMLTreeNode( SvgXML, 0 )
     scaling = XML_tree.scaling()
     for element in XML_tree.getAllElements():
         if element.tag != element_tag_of_interest:
             continue
         if element.tag == 'circle':
             x, y = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
             r =  float( element.parms['r'] )* scaling
             self.circles.append( [ x, y, r] )
             self.ellipse_points( x, y, r, r )
         if element.tag == 'ellipse': #no angle parm?
             cx, cy = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
             rx, ry = float( element.parms['rx'] )* scaling, float( element.parms['ry'] )* scaling
             self.ellipses.append( [ cx, cy, rx, ry] )
             self.ellipse_points( cx, cy, rx, ry )
         if element.tag == 'text' and element.parms.has_key('x'):
             x, y = element.applyTransforms( float( element.parms['x'] ), float( element.parms['y'] ) )
             self.texts.append( [x, y, element] )
         if element.tag == 'path': 
             path = SvgPath( element )
             for p in path.points:
                 self.points.append( [p.x, p.y] )
             for line in path.lines:
                 self.lines.append([ line.x1, line.y1, line.x2, line.y2 ])
                 self.points.append( line.midPoint() )
             for arc in path.arcs:
                 if arc.circular:
                     self.circles.append( [arc.center[0], arc.center[1], arc.r*scaling] )
                 else:
                     self.ellipses.append( [arc.center[0], arc.center[1], arc.rX*scaling, arc.rY*scaling ] )
                 self.points.append( [arc.center[0], arc.center[1]] )
             if doFittedCircles:
                 for bezierCurve in path.bezierCurves:
                     x, y, r, r_error = bezierCurve.fitCircle()
                     if r_error < 10**-4:
                         self.circles.append( [ x, y, r] )
         if element.tag == 'line':
             x1, y1 = element.applyTransforms( float( element.parms['x1'] ), float( element.parms['y1'] ) )
             x2, y2 = element.applyTransforms( float( element.parms['x2'] ), float( element.parms['y2'] ) )
             self.points.append( [x1, y1] )
             self.points.append( [x2, y2] )
             self.points.append( [(x1+x2)/2, (y1+y2)/2] )
             self.lines.append(  [x1, y1, x2, y2 ] )
コード例 #7
0
def generateSelectionGraphicsItems( viewObjects, onClickFun, transform=None, sceneToAddTo=None, clearPreviousSelectionItems=True,
                                    doPoints=False, doTextItems=False, doLines=False, doCircles=False, doFittedCircles=False, 
                                    pointWid=1.0 , maskPen=defaultMaskPen , maskBrush=defaultMaskBrush, maskHoverPen=defaultMaskHoverPen ):
    if clearPreviousSelectionItems:
        del graphicItems[:] #may cause problems, if conflict results with FreeCAD recompute function
    def postProcessGraphicsItem(gi, elementParms):
        gi.setBrush( maskBrush  )
        gi.setPen(maskPen)
        gi.selectionMaskPen = maskPen
        gi.selectionMaskHoverPen = maskHoverPen
        gi._onClickFun = onClickFun
        gi.elementParms = elementParms
        gi.elementXML = element #should be able to get from functions name space
        gi.elementViewObject = viewObject
        gi.setAcceptHoverEvents(True)
        gi.setCursor( QtCore.Qt.CrossCursor ) # http://qt-project.org/doc/qt-5/qt.html#CursorShape-enum
        if transform <> None:
            gi.setTransform( transform )
        if sceneToAddTo <> None:
            sceneToAddTo.addItem(gi)
        graphicItems.append(gi)
    pointsAlreadyAdded = []
    def addSelectionPoint( x, y ): #common code
        if [x,y] in pointsAlreadyAdded:
            return
        pointsAlreadyAdded.append( [x,y] )
        graphicsItem = CircleSelectionGraphicsItem( x-pointWid, y-pointWid, 2*pointWid, 2*pointWid )
        graphicsItem.setZValue( 1 ) #point on top!
        postProcessGraphicsItem(graphicsItem, {'x':x, 'y':y})

    for viewObject in viewObjects:
        if viewObject.ViewResult.strip() == '':
            pass
        XML_tree =  SvgXMLTreeNode(viewObject.ViewResult,0)
        scaling = XML_tree.scaling()
        for element in XML_tree.getAllElements():
            if element.tag == 'circle':
                x, y = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
                r =  float( element.parms['r'] )* scaling
                if doCircles:
                    graphicsItem = CircleSelectionGraphicsItem( x-r, y-r, 2*r, 2*r )
                    graphicsItem.setZValue( 1.01**-r ) #smaller circles on top
                    postProcessGraphicsItem(graphicsItem, {'x':x,'y':y,'r':r})
                if doPoints: 
                    addSelectionPoint ( x, y ) #Circle center point
                    addSelectionPoint ( x + r, y ) #Circle right quadrant point
                    addSelectionPoint ( x - r, y ) #Circle left quadrant point
                    addSelectionPoint ( x , y + r ) #Circle top quadrant point
                    addSelectionPoint ( x , y - r ) #Circle bottom quadrant point
                    
            if element.tag == 'text' and doTextItems:
                addSelectionPoint( *element.applyTransforms( float( element.parms['x'] ), float( element.parms['y'] ) ) )
            if element.tag == 'path':
                #print(element.XML)
                fitData = []
                dParmsXML = element.parms['d']
                #<spacing corrections>
                i = 0
                while i < len(dParmsXML)-1:
                    if dParmsXML[i] in 'MLACQ,' and dParmsXML[i+1] in '-.0123456789':
                        dParmsXML = dParmsXML[:i+1] + ' ' + dParmsXML[i+1:]
                    i = i + 1
                #</spacing corrections>
                parms = dParmsXML.replace(',',' ').strip().split()
                j = 0
                while j < len(parms):
                    #print(parms[j:])
                    if parms[j] == 'M':
                        pen_x, pen_y = element.applyTransforms( float(parms[j+1]), float(parms[j+2]) )
                        j = j + 3
                    elif parms[j] == 'L':
                        end_x, end_y = element.applyTransforms( float(parms[j+1]), float(parms[j+2]) )
                        if doPoints:
                            addSelectionPoint ( pen_x, pen_y )
                            addSelectionPoint ( end_x, end_y )
                        if doLines:
                            graphicsItem = LineSelectionGraphicsItem( pen_x, pen_y, end_x, end_y )
                            postProcessGraphicsItem(graphicsItem, {'x1':pen_x,'y1':pen_y,'x2':end_x,'y2':end_y})
                        pen_x, pen_y = end_x, end_y
                        j = j + 3
                    elif parms[j] == 'A':
                        # The arc command begins with the x and y radius and ends with the ending point of the arc. 
                        # Between these are three other values: x axis rotation, large arc flag and sweep flag.
                        rX, rY, xRotation, largeArc, sweep, _end_x, _end_y = map( float, parms[j+1:j+1 + 7] )
                        end_x, end_y = element.applyTransforms( _end_x, _end_y )
                        if doPoints:
                            addSelectionPoint ( pen_x, pen_y )
                            addSelectionPoint ( end_x, end_y )
                        if doFittedCircles :
                            pass #not implement yet for arcs ...
                        pen_x, pen_y = end_x, end_y
                        j = j + 8
                    elif parms[j] == 'C' or parms[j] =='Q': #Bézier curve 
                        if parms[j] == 'C':
                            #cubic Bézier curve from the current point to (x,y) using 
                            # (x1,y1) as the control point at the beginning of the curve and (x2,y2) as the control point at the end of the curve.
                            _x1, _y1, _x2, _y2, _end_x, _end_y = map( float, parms[j+1:j+1 + 6] ) 
                            P = [ [pen_x, pen_y], element.applyTransforms(_x1, _y1), element.applyTransforms(_x2, _y2), element.applyTransforms(_end_x, _end_y) ]
                        elif parms[j] == 'Q': # quadratic Bézier curve from the current point to (x,y) using (x1,y1) as the control point. 
                            # Q (uppercase) indicates that absolute coordinates will follow; 
                            # q (lowercase) indicates that relative coordinates will follow. 
                            # Multiple sets of coordinates may be specified to draw a polybézier. 
                            # At the end of the command, the new current point becomes the final (x,y) coordinate pair used in the polybézier.
                            _x1, _y1, _end_x, _end_y = map( float, parms[j+1:j+1 + 4] ) 
                            P = [ [pen_x, pen_y], element.applyTransforms(_x1, _y1), element.applyTransforms(_end_x, _end_y) ]
                        end_x, end_y = P[-1]
                        if doPoints:
                            addSelectionPoint ( pen_x, pen_y )
                            addSelectionPoint ( end_x, end_y )
                        if doFittedCircles :
                            fitData.append( P )
                        pen_x, pen_y = end_x, end_y
                        j = j + 7
                    else:
                        raise RuntimeError, 'unable to parse path "%s" with d parms %s' % (element.XML[element.pStart: element.pEnd], parms)
                if len(fitData) > 0: 
                    x, y, r, r_error = bezier_curve_lib.fitCircle_to_path(fitData)
                    #print('fittedCircle: x, y, r, r_error', x, y, r, r_error)
                    if r_error < 10**-4:
                        graphicsItem = CircleSelectionGraphicsItem( x-r, y-r, 2*r, 2*r )
                        graphicsItem.setZValue( 1.01**-r ) #smaller circles on top
                        postProcessGraphicsItem(graphicsItem, {'x':x,'y':y,'r':r, 'r_error':r_error})
                        #self.fitted_circles.append( FittedCircle( element, fitData, cx, cy, r) )
    return graphicItems
コード例 #8
0
def export_via_dxfwrite(  dxf_fn, V):
    from XMLlib import SvgXMLTreeNode
    from svgLib_dd import SvgTextParser, SvgPath, SvgPolygon
    from numpy import arctan2
    from circleLib import fitCircle_to_path, findCircularArcCentrePoint, pointsAlongCircularArc
    from dxfwrite import DXFEngine as dxf
    drawing = dxf.drawing( dxf_fn)
    
    pageSvg = open(V.page.PageResult).read()
    XML_tree =  SvgXMLTreeNode( pageSvg,0)
    def yT(y): #y transform
        return 210-y
    warningsShown = []
    SelectViewObjectPoint_loc = None
    for element in XML_tree.getAllElements():
        clr_text = None        
        if element.parms.has_key('fill'):
            clr_text =  element.parms['fill']
        elif element.parms.has_key('style'):
            for part in element.parms['style'].split(';'):
                if part.startswith('stroke:rgb('):
                    clr_text = part[ len('stroke:'):]
        if clr_text == None or clr_text =='none' or not clr_text.startswith('rgb(') :
            color_code = 0
        else:
            #FreeCAD.Console.PrintMessage( "color text: %s\n" % clr_text )
            r,g,b = [ int(v.strip()) for v in clr_text[ len('rgb('): clr_text.find(')')].split(',') ]
            color_code = colorLookup(r,g,b)[0]
        if element.tag == 'circle':
            x, y = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
            r =  float( element.parms['r'] )* element.scaling2()
            drawing.add( dxf.circle( r, (x,yT(y)), color=color_code) )
        elif element.tag == 'line':
            x1, y1 = element.applyTransforms( float( element.parms['x1'] ), float( element.parms['y1'] ) )
            x2, y2 = element.applyTransforms( float( element.parms['x2'] ), float( element.parms['y2'] ) )
            drawing.add( dxf.line( (x1, yT(y1)), (x2, yT(y2)), color=color_code ) )
        elif element.tag == 'text' and element.parms.has_key('x'):
            x,y = element.applyTransforms( float( element.parms['x'] ), float( element.parms['y'] ) )
            try:
                t = SvgTextParser(element.XML[element.pStart: element.pEnd ] )
                drawing.add(dxf.text( t.text, insert=(x, yT(y)), height=t.height()*0.8, rotation=t.rotation, layer='TEXTLAYER', color=color_code) )
            except ValueError, msg:
                FreeCAD.Console.PrintWarning('dxf_export: unable to convert text element "%s": %s, ignoring...\n' % (element.XML[element.pStart: element.pEnd ], str(msg) ) )
        elif element.tag == 'path': 
            #FreeCAD.Console.PrintMessage(element.parms['d']+'\n')
            path = SvgPath( element )
            for line in path.lines:
                drawing.add( dxf.line( (line.x1, yT(line.y1)), (line.x2,yT(line.y2)), color=color_code) ) 
            for arc in path.arcs:
                if arc.circular:
                    for r, center, angle1, angle2 in arc.dxfwrite_arc_parms( yT ):
                        drawing.add( dxf.arc( r, center, angle1, angle2 , color=color_code) )
                else:
                    for x1,y1,x2,y2 in arc.approximate_via_lines( 12 ):
                        drawing.add( dxf.line( (x1, yT(y1)), (x2, yT(y2)), color=color_code) )
            for bezierCurve in path.bezierCurves:
                x, y, r, r_error = bezierCurve.fitCircle()
                if r_error < 10**-4:
                    raise NotImplementedError
                    drawing.add( dxf.arc( *bezierCurve.dxfwrite_arc_parms(x, y, r) ) )
                else:
                    X,Y = bezierCurve.points_along_curve()
                    for i in range(len(X) -1):
                        drawing.add( dxf.line( (X[i], yT(Y[i])), (X[i+1],yT(Y[i+1])), color=color_code ) )
コード例 #9
0
def generateSelectionGraphicsItems( viewObjects, onClickFun, transform=None, sceneToAddTo=None, clearPreviousSelectionItems=True, 
                                    doPoints=False, doTextItems=False, doLines=False, doCircles=False, doFittedCircles=False, doPathEndPoints=False, doMidPoints=False, doSelectViewObjectPoints=False,
                                    pointWid=1.0 , maskPen=defaultMaskPen , maskBrush=defaultMaskBrush, maskHoverPen=defaultMaskHoverPen ):
    if clearPreviousSelectionItems:         
        if sceneToAddTo <> None:
            for gi in sceneToAddTo.items():
                if isinstance(gi, CircleSelectionGraphicsItem):
                    sceneToAddTo.removeItem(gi)
        del graphicItems[:]
    def postProcessGraphicsItem(gi, elementParms, zValue=0.99):
        gi.setBrush( maskBrush  )
        gi.setPen(maskPen)
        gi.selectionMaskPen = QtGui.QPen(maskPen)
        gi.selectionMaskHoverPen = QtGui.QPen(maskHoverPen)
        gi._onClickFun = onClickFun
        gi.elementParms = elementParms
        gi.elementXML = element #should be able to get from functions name space
        gi.elementViewObject = viewObject
        gi.setAcceptHoverEvents(True)
        gi.setCursor( QtCore.Qt.CrossCursor ) # http://qt-project.org/doc/qt-5/qt.html#CursorShape-enum ; may not work for lines ...
        gi.setZValue(zValue)
        if transform <> None:
            gi.setTransform( transform )
        if sceneToAddTo <> None:
            sceneToAddTo.addItem(gi)
        graphicItems.append(gi)
    pointsAlreadyAdded = []
    def addSelectionPoint( x, y, zValue=1.0 ): #common code
        if [x,y] in pointsAlreadyAdded:
            return
        pointsAlreadyAdded.append( [x,y] )
        graphicsItem = PointSelectionGraphicsItem( x-pointWid, y-pointWid, 2*pointWid, 2*pointWid )
        postProcessGraphicsItem(graphicsItem, {'x':x, 'y':y}, zValue)
    def addCircle( x, y, r, **extraKWs):
        graphicsItem = CircleSelectionGraphicsItem( x-r, y-r, 2*r, 2*r )
        KWs = {'x':x,'y':y,'r':r}
        KWs.update(extraKWs)
        postProcessGraphicsItem(graphicsItem, KWs, zValue=1.01**-r ) #smaller circles on top
    def circlePoints( x, y, rx, ry ):
        addSelectionPoint ( x, y, 2 ) #Circle/ellipse center point
        addSelectionPoint ( x + rx, y, 2 ) #Circle/ellipse right quadrant point
        addSelectionPoint ( x - rx, y, 2 ) #Circle/ellipse left quadrant point
        addSelectionPoint ( x , y + ry, 2 ) #Circle/ellipse top quadrant point
        addSelectionPoint ( x , y - ry, 2 ) #Circle/ellipse bottom quadrant point

    for viewObject in viewObjects:
        if not hasattr(viewObject, 'ViewResult'):
            continue
        if viewObject.ViewResult.strip() == '':
            continue
        XML_tree =  SvgXMLTreeNode(viewObject.ViewResult,0)
        scaling = XML_tree.scaling()
        SelectViewObjectPoint_loc = None
        for element in XML_tree.getAllElements():
            if element.tag == 'circle':
                x, y = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
                r =  float( element.parms['r'] )* scaling
                if doCircles: 
                    addCircle( x, y, r)
                if doPoints: 
                    circlePoints( x, y, r, r)
            if element.tag == 'ellipse':
                cx, cy = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
                rx, ry = float( element.parms['rx'] )* scaling, float( element.parms['ry'] )* scaling
                if doCircles: 
                    if rx == ry:
                        addCircle( cx, cy, rx)
                if doPoints: 
                    circlePoints( cx, cy, rx, ry)
                
            if element.tag == 'text' and element.parms.has_key('x'):
                if doTextItems:
                    addSelectionPoint( *element.applyTransforms( float( element.parms['x'] ), float( element.parms['y'] ) ) )
                elif doSelectViewObjectPoints:
                    addSelectionPoint( *element.applyTransforms( float( element.parms['x'] ), float( element.parms['y'] ) ) )

            if element.tag == 'path': 
                path = SvgPath( element )
                if doPoints:
                    for p in path.points:
                         addSelectionPoint( p.x, p.y )
                if doLines:
                    for line in path.lines:
                        x1, y1, x2, y2 = line.x1, line.y1, line.x2, line.y2
                        graphicsItem = LineSelectionGraphicsItem( x1, y1, x2, y2 )
                        postProcessGraphicsItem(graphicsItem, {'x1':x1,'y1':y1,'x2':x2,'y2':y2} )
                if doMidPoints:
                    for line in path.lines:
                        addSelectionPoint( *line.midPoint() )
                if doCircles:
                    for arc in path.arcs:
                        if arc.circular:
                            gi = PathSelectionGraphicsItem()
                            gi.setPath( arc.svgPath() )
                            postProcessGraphicsItem( gi, {'x': arc.c_x,'y': arc.c_y,'r': arc.r*scaling, 'largeArc': arc.largeArc, 'sweep': arc.sweep,  } )
                if doFittedCircles:
                    for bezierCurve in path.bezierCurves:
                        x, y, r, r_error = bezierCurve.fitCircle()
                        if r_error < 10**-4:
                            gi = PathSelectionGraphicsItem()
                            gi.setPath( bezierCurve.svgPath() )
                            postProcessGraphicsItem( gi, {'x':x,'y':y,'r':r} )
                if doPathEndPoints and len(path.points) > 0:
                    addSelectionPoint ( path.points[-1].x,  path.points[-1].y )
                if doSelectViewObjectPoints and SelectViewObjectPoint_loc == None and len(path.points) > 0:
                    SelectViewObjectPoint_loc = path.points[-1].x,  path.points[-1].y

            if element.tag == 'line':
                x1, y1 = element.applyTransforms( float( element.parms['x1'] ), float( element.parms['y1'] ) )
                x2, y2 = element.applyTransforms( float( element.parms['x2'] ), float( element.parms['y2'] ) )
                if doPoints:
                    addSelectionPoint ( x1, y1 )
                    addSelectionPoint ( x2, y2 )
                if doLines:
                    graphicsItem = LineSelectionGraphicsItem( x1, y1, x2, y2 )
                    postProcessGraphicsItem(graphicsItem, {'x1':x1,'y1':y1,'x2':x2,'y2':y2})
                if doMidPoints:
                    addSelectionPoint( (x1+x2)/2, (y1+y2)/2 )
                if doSelectViewObjectPoints and SelectViewObjectPoint_loc == None: #second check to textElementes preference
                    SelectViewObjectPoint_loc = x2, y2

        if doSelectViewObjectPoints and SelectViewObjectPoint_loc <> None:
            addSelectionPoint( *SelectViewObjectPoint_loc )
                #if len(fitData) > 0: 
                #    x, y, r, r_error = fitCircle_to_path(fitData)
                #    #print('fittedCircle: x, y, r, r_error', x, y, r, r_error)
                #    if r_error < 10**-4:
                #        if doFittedCircles:
                #            addCircle( x, y, r , r_error=r_error )
                #        if doPoints:
                #            circlePoints( x, y, r, r)

    return graphicItems
コード例 #10
0
def generateSelectionGraphicsItems( viewObjects, onClickFun, transform=None, sceneToAddTo=None, clearPreviousSelectionItems=True, 
                                    doPoints=False, doTextItems=False, doLines=False, doCircles=False, doFittedCircles=False, doPathEndPoints=False, doMidPoints=False, doSelectViewObjectPoints=False,
                                    pointWid=1.0 , maskPen=defaultMaskPen , maskBrush=defaultMaskBrush, maskHoverPen=defaultMaskHoverPen ):
    if clearPreviousSelectionItems:         
        if sceneToAddTo <> None:
            for gi in sceneToAddTo.items():
                if isinstance(gi, CircleSelectionGraphicsItem):
                    sceneToAddTo.removeItem(gi)
        del graphicItems[:]
    def postProcessGraphicsItem(gi, elementParms, zValue=0.99):
        gi.setBrush( maskBrush  )
        gi.setPen(maskPen)
        gi.selectionMaskPen = QtGui.QPen(maskPen)
        gi.selectionMaskHoverPen = QtGui.QPen(maskHoverPen)
        gi._onClickFun = onClickFun
        gi.elementParms = elementParms
        gi.elementXML = element #should be able to get from functions name space
        gi.elementViewObject = viewObject
        gi.setAcceptHoverEvents(True)
        gi.setCursor( QtCore.Qt.CrossCursor ) # http://qt-project.org/doc/qt-5/qt.html#CursorShape-enum ; may not work for lines ...
        gi.setZValue(zValue)
        if transform <> None:
            gi.setTransform( transform )
        if sceneToAddTo <> None:
            sceneToAddTo.addItem(gi)
        graphicItems.append(gi)
    pointsAlreadyAdded = []
    def addSelectionPoint( x, y, zValue=1.0 ): #common code
        if [x,y] in pointsAlreadyAdded:
            return
        pointsAlreadyAdded.append( [x,y] )
        graphicsItem = PointSelectionGraphicsItem( x-pointWid, y-pointWid, 2*pointWid, 2*pointWid )
        postProcessGraphicsItem(graphicsItem, {'x':x, 'y':y}, zValue)
    def addCircle( x, y, r, **extraKWs):
        graphicsItem = CircleSelectionGraphicsItem( x-r, y-r, 2*r, 2*r )
        KWs = {'x':x,'y':y,'r':r}
        KWs.update(extraKWs)
        postProcessGraphicsItem(graphicsItem, KWs, zValue=1.01**-r ) #smaller circles on top
    def circlePoints( x, y, rx, ry ):
        addSelectionPoint ( x, y, 2 ) #Circle/ellipse center point
        addSelectionPoint ( x + rx, y, 2 ) #Circle/ellipse right quadrant point
        addSelectionPoint ( x - rx, y, 2 ) #Circle/ellipse left quadrant point
        addSelectionPoint ( x , y + ry, 2 ) #Circle/ellipse top quadrant point
        addSelectionPoint ( x , y - ry, 2 ) #Circle/ellipse bottom quadrant point

    for viewObject in viewObjects:
        if viewObject.ViewResult.strip() == '':
            continue
        XML_tree =  SvgXMLTreeNode(viewObject.ViewResult,0)
        scaling = XML_tree.scaling()
        SelectViewObjectPoint_loc = None
        for element in XML_tree.getAllElements():
            if element.tag == 'circle':
                x, y = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
                r =  float( element.parms['r'] )* scaling
                if doCircles: 
                    addCircle( x, y, r)
                if doPoints: 
                    circlePoints( x, y, r, r)
            if element.tag == 'ellipse':
                cx, cy = element.applyTransforms( float( element.parms['cx'] ), float( element.parms['cy'] ) )
                rx, ry = float( element.parms['rx'] )* scaling, float( element.parms['ry'] )* scaling
                if doCircles: 
                    if rx == ry:
                        addCircle( cx, cy, rx)
                if doPoints: 
                    circlePoints( cx, cy, rx, ry)
                
            if element.tag == 'text' and element.parms.has_key('x'):
                if doTextItems:
                    addSelectionPoint( *element.applyTransforms( float( element.parms['x'] ), float( element.parms['y'] ) ) )
                elif doSelectViewObjectPoints:
                    addSelectionPoint( *element.applyTransforms( float( element.parms['x'] ), float( element.parms['y'] ) ) )

            if element.tag == 'path': #https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
                #print(element.XML)
                fitData = []
                dParmsXML = element.parms['d']
                #<spacing corrections>
                i = 0
                while i < len(dParmsXML)-1:
                    if dParmsXML[i] in 'MmLlACcQZz,' and dParmsXML[i+1] in '-.0123456789':
                        dParmsXML = dParmsXML[:i+1] + ' ' + dParmsXML[i+1:]
                    i = i + 1
                #</spacing corrections>
                parms = dParmsXML.replace(',',' ').strip().split()
                _pen_x = 0
                _pen_y = 0
                j = 0
                pathDescriptor = None
                while j < len(parms):
                    #print(parms[j:])
                    if parms[j] in list('MmLlACcQZz,'):
                        pathDescriptor = parms[j]
                    else: #using previous pathDescriptor
                        if pathDescriptor == None:
                            raise RuntimeError, 'pathDescriptor == None! unable to parse path "%s" with d parms %s' % (element.XML[element.pStart: element.pEnd], parms)
                        parms.insert(j, pathDescriptor.replace('m','l').replace('M','L'))

                    if parms[j] == 'M' or parms[j] == 'm':
                        if parms[j] == 'M':
                            _pen_x, _pen_y = float(parms[j+1]), float(parms[j+2])
                        else:
                            _pen_x = _pen_x + float(parms[j+1])
                            _pen_y = _pen_y + float(parms[j+2])
                        pen_x, pen_y = element.applyTransforms( _pen_x, _pen_y )
                        _path_start_x , _path_start_y = _pen_x, _pen_y
                        path_start_x , path_start_y = pen_x, pen_y
                        j = j + 3                        
                    elif parms[j] in ['L','l','Z','z']:
                        if  parms[j] == 'L' or parms[j] == 'l':
                            if parms[j] == 'L':
                                _end_x, _end_y = float(parms[j+1]), float(parms[j+2])
                            else:
                                _end_x = _pen_x + float(parms[j+1])
                                _end_y = _pen_y + float(parms[j+2])
                            end_x, end_y = element.applyTransforms( _end_x, _end_y )
                            j = j + 3
                        else: #parms[j] == 'Z':
                            _end_x, _end_y = _path_start_x , _path_start_y
                            end_x, end_y = path_start_x , path_start_y
                            j = j + 1
                        if doPoints:
                            addSelectionPoint ( pen_x, pen_y )
                            addSelectionPoint ( end_x, end_y )
                        if doLines:
                            graphicsItem = LineSelectionGraphicsItem( pen_x, pen_y, end_x, end_y )
                            postProcessGraphicsItem(graphicsItem, {'x1':pen_x,'y1':pen_y,'x2':end_x,'y2':end_y})
                        if doMidPoints:
                            addSelectionPoint( (pen_x+end_x)/2, (pen_y+end_y)/2 )
                        _pen_x, _pen_y = _end_x, _end_y
                        pen_x, pen_y = end_x, end_y
                    elif parms[j] == 'A':
                        # The arc command begins with the x and y radius and ends with the ending point of the arc. 
                        # Between these are three other values: x axis rotation, large arc flag and sweep flag.
                        rX, rY, xRotation, largeArc, sweep, _end_x, _end_y = map( float, parms[j+1:j+1 + 7] )
                        end_x, end_y = element.applyTransforms( _end_x, _end_y )
                        if doPoints:
                            addSelectionPoint ( pen_x, pen_y )
                            addSelectionPoint ( end_x, end_y )
                        if rX==rY :
                            _c_x, _c_y = findCircularArcCentrePoint( rX, _pen_x, _pen_y, _end_x, _end_y, largeArc==1, sweep==1 ) #do in untranformed co-ordinates as to preserve sweep flag
                            if not numpy.isnan(_c_x): #if all went well findCircularArcCentrePoint
                                c_x, c_y = element.applyTransforms( _c_x, _c_y )
                                r = rX * scaling
                                if doCircles: 
                                    #addCircle( c_x, c_y, r , largeArc=largeArc, sweep=sweep)
                                    gi = PathSelectionGraphicsItem()
                                    path = QtGui.QPainterPath(QtCore.QPointF(pen_x, pen_y))
                                    #path.arcTo(c_x - r, c_y -r , 2*r, 2*r, angle_1, angle_CCW) #dont know what is up with this function so trying something else.
                                    for _p in pointsAlongCircularArc(rX, _pen_x, _pen_y, _end_x, _end_y, largeArc==1, sweep==1, noPoints=12):
                                        path.lineTo(* element.applyTransforms(*_p) )
                                    gi.setPath(path)
                                    postProcessGraphicsItem( gi, {'x':c_x,'y':c_y,'r':r, 'largeArc':largeArc, 'sweep':sweep,  } )
                                #if doPoints:
                                #    circlePoints( c_x, c_y, r, r)
                        _pen_x, _pen_y = _end_x, _end_y
                        pen_x, pen_y = end_x, end_y
                        j = j + 8
                    elif parms[j] == 'C' or parms[j] == 'c' or parms[j] =='Q': #Bézier curve 
                        if parms[j] == 'C' or parms[j] == 'c':
                            #cubic Bézier curve from the current point to (x,y) using 
                            # (x1,y1) as the control point at the beginning of the curve and (x2,y2) as the control point at the end of the curve.
                            if parms[j] == 'C':
                                _x1, _y1, _x2, _y2, _end_x, _end_y = map( float, parms[j+1:j+1 + 6] ) 
                            else: #parms[j] == 'c':
                                _x1, _y1, _x2, _y2, _end_x, _end_y = numpy.array(map( float, parms[j+1:j+1 + 6] )) + numpy.array([_pen_x,_pen_y]*3)
                            P = [ [pen_x, pen_y], element.applyTransforms(_x1, _y1), element.applyTransforms(_x2, _y2), element.applyTransforms(_end_x, _end_y) ]
                            j = j + 7
                        elif parms[j] == 'Q': # quadratic Bézier curve from the current point to (x,y) using (x1,y1) as the control point. 
                            # Q (uppercase) indicates that absolute coordinates will follow; 
                            # q (lowercase) indicates that relative coordinates will follow. 
                            # Multiple sets of coordinates may be specified to draw a polybézier. 
                            # At the end of the command, the new current point becomes the final (x,y) coordinate pair used in the polybézier.
                            _x1, _y1, _end_x, _end_y = map( float, parms[j+1:j+1 + 4] ) 
                            j = j + 5
                            P = [ [pen_x, pen_y], element.applyTransforms(_x1, _y1), element.applyTransforms(_end_x, _end_y) ]
                        if doFittedCircles:
                            x, y, r, r_error = fitCircle_to_path([P])
                            #print('fittedCircle: x, y, r, r_error', x, y, r, r_error)
                            if r_error < 10**-4:
                                gi = PathSelectionGraphicsItem()
                                path = QtGui.QPainterPath(QtCore.QPointF(pen_x, pen_y))
                                if len(P) == 4:
                                    path.cubicTo( QtCore.QPointF(*P[1]), QtCore.QPointF(*P[2]), QtCore.QPointF(*P[3]) )
                                else:
                                    path.quadTo( QtCore.QPointF(*P[1]), QtCore.QPointF(*P[2]) )
                                gi.setPath(path)
                                postProcessGraphicsItem( gi, {'x':x,'y':y,'r':r} )

                        end_x, end_y = P[-1]
                        if doPoints:
                            addSelectionPoint ( pen_x, pen_y )
                            addSelectionPoint ( end_x, end_y )
                        #fitData.append( P )
                        _pen_x, _pen_y = _end_x, _end_y
                        pen_x, pen_y = end_x, end_y
                    else:
                        raise RuntimeError, 'unable to parse path "%s" with d parms %s' % (element.XML[element.pStart: element.pEnd], parms)
                if j > 0 and doPathEndPoints:
                    addSelectionPoint ( pen_x, pen_y )
                if j > 0 and doSelectViewObjectPoints and SelectViewObjectPoint_loc == None:
                    SelectViewObjectPoint_loc = pen_x, pen_y

            if element.tag == 'line':
                x1, y1 = element.applyTransforms( float( element.parms['x1'] ), float( element.parms['y1'] ) )
                x2, y2 = element.applyTransforms( float( element.parms['x2'] ), float( element.parms['y2'] ) )
                if doPoints:
                    addSelectionPoint ( x1, y1 )
                    addSelectionPoint ( x2, y2 )
                if doLines:
                    graphicsItem = LineSelectionGraphicsItem( x1, y1, x2, y2 )
                    postProcessGraphicsItem(graphicsItem, {'x1':x1,'y1':y1,'x2':x2,'y2':y2})
                if doMidPoints:
                    addSelectionPoint( (x1+x2)/2, (y1+y2)/2 )
                if doSelectViewObjectPoints and SelectViewObjectPoint_loc == None: #second check to textElementes preference
                    SelectViewObjectPoint_loc = x2,y2

        if doSelectViewObjectPoints and SelectViewObjectPoint_loc <> None:
            addSelectionPoint( *SelectViewObjectPoint_loc )
                #if len(fitData) > 0: 
                #    x, y, r, r_error = fitCircle_to_path(fitData)
                #    #print('fittedCircle: x, y, r, r_error', x, y, r, r_error)
                #    if r_error < 10**-4:
                #        if doFittedCircles:
                #            addCircle( x, y, r , r_error=r_error )
                #        if doPoints:
                #            circlePoints( x, y, r, r)

    return graphicItems
コード例 #11
0
def export_via_dxfwrite(dxf_fn, V):
    from XMLlib import SvgXMLTreeNode
    from svgLib_dd import SvgTextParser, SvgPath, SvgPolygon
    from numpy import arctan2
    from circleLib import fitCircle_to_path, findCircularArcCentrePoint, pointsAlongCircularArc
    from dxfwrite import DXFEngine as dxf
    drawing = dxf.drawing(dxf_fn)

    pageSvg = open(V.page.PageResult).read()
    XML_tree = SvgXMLTreeNode(pageSvg, 0)

    def yT(y):  #y transform
        return 210 - y

    warningsShown = []
    SelectViewObjectPoint_loc = None
    for element in XML_tree.getAllElements():
        clr_text = None
        if element.parms.has_key('fill'):
            clr_text = element.parms['fill']
        elif element.parms.has_key('style'):
            for part in element.parms['style'].split(';'):
                if part.startswith('stroke:rgb('):
                    clr_text = part[len('stroke:'):]
        if clr_text == None or clr_text == 'none' or not clr_text.startswith(
                'rgb('):
            color_code = 0
        else:
            #FreeCAD.Console.PrintMessage( "color text: %s\n" % clr_text )
            r, g, b = [
                int(v.strip())
                for v in clr_text[len('rgb('):clr_text.find(')')].split(',')
            ]
            color_code = colorLookup(r, g, b)[0]
        if element.tag == 'circle':
            x, y = element.applyTransforms(float(element.parms['cx']),
                                           float(element.parms['cy']))
            r = float(element.parms['r']) * element.scaling2()
            drawing.add(dxf.circle(r, (x, yT(y)), color=color_code))
        elif element.tag == 'line':
            x1, y1 = element.applyTransforms(float(element.parms['x1']),
                                             float(element.parms['y1']))
            x2, y2 = element.applyTransforms(float(element.parms['x2']),
                                             float(element.parms['y2']))
            drawing.add(dxf.line((x1, yT(y1)), (x2, yT(y2)), color=color_code))
        elif element.tag == 'text' and element.parms.has_key('x'):
            x, y = element.applyTransforms(float(element.parms['x']),
                                           float(element.parms['y']))
            try:
                t = SvgTextParser(element.XML[element.pStart:element.pEnd])
                drawing.add(
                    dxf.text(t.text,
                             insert=(x, yT(y)),
                             height=t.height() * 0.8,
                             rotation=t.rotation,
                             layer='TEXTLAYER',
                             color=color_code))
            except ValueError, msg:
                FreeCAD.Console.PrintWarning(
                    'dxf_export: unable to convert text element "%s": %s, ignoring...\n'
                    % (element.XML[element.pStart:element.pEnd], str(msg)))
        elif element.tag == 'path':
            #FreeCAD.Console.PrintMessage(element.parms['d']+'\n')
            path = SvgPath(element)
            for line in path.lines:
                drawing.add(
                    dxf.line((line.x1, yT(line.y1)), (line.x2, yT(line.y2)),
                             color=color_code))
            for arc in path.arcs:
                if arc.circular:
                    for r, center, angle1, angle2 in arc.dxfwrite_arc_parms(
                            yT):
                        drawing.add(
                            dxf.arc(r,
                                    center,
                                    angle1,
                                    angle2,
                                    color=color_code))
                else:
                    for x1, y1, x2, y2 in arc.approximate_via_lines(12):
                        drawing.add(
                            dxf.line((x1, yT(y1)), (x2, yT(y2)),
                                     color=color_code))
            for bezierCurve in path.bezierCurves:
                x, y, r, r_error = bezierCurve.fitCircle()
                if r_error < 10**-4:
                    raise NotImplementedError
                    drawing.add(
                        dxf.arc(*bezierCurve.dxfwrite_arc_parms(x, y, r)))
                else:
                    X, Y = bezierCurve.points_along_curve()
                    for i in range(len(X) - 1):
                        drawing.add(
                            dxf.line((X[i], yT(Y[i])),
                                     (X[i + 1], yT(Y[i + 1])),
                                     color=color_code))
コード例 #12
0
def generateSelectionGraphicsItems(viewObjects,
                                   onClickFun,
                                   transform=None,
                                   sceneToAddTo=None,
                                   clearPreviousSelectionItems=True,
                                   doPoints=False,
                                   doTextItems=False,
                                   doLines=False,
                                   doCircles=False,
                                   doFittedCircles=False,
                                   doPathEndPoints=False,
                                   doMidPoints=False,
                                   doSelectViewObjectPoints=True,
                                   pointWid=1.0,
                                   maskPen=defaultMaskPen,
                                   maskBrush=defaultMaskBrush,
                                   maskHoverPen=defaultMaskHoverPen):
    if clearPreviousSelectionItems:
        if sceneToAddTo <> None:
            for gi in sceneToAddTo.items():
                if isinstance(gi, CircleSelectionGraphicsItem):
                    sceneToAddTo.removeItem(gi)
        del graphicItems[:]

    def postProcessGraphicsItem(gi, elementParms, zValue=0.99):
        gi.setBrush(maskBrush)
        gi.setPen(maskPen)
        gi.selectionMaskPen = QtGui.QPen(maskPen)
        gi.selectionMaskHoverPen = QtGui.QPen(maskHoverPen)
        gi._onClickFun = onClickFun
        gi.elementParms = elementParms
        gi.elementXML = element  #should be able to get from functions name space
        gi.elementViewObject = viewObject
        gi.setAcceptHoverEvents(True)
        gi.setCursor(
            QtCore.Qt.CrossCursor
        )  # http://qt-project.org/doc/qt-5/qt.html#CursorShape-enum ; may not work for lines ...
        gi.setZValue(zValue)
        if transform <> None:
            gi.setTransform(transform)
        if sceneToAddTo <> None:
            sceneToAddTo.addItem(gi)
        graphicItems.append(gi)

    pointsAlreadyAdded = []

    def addSelectionPoint(x, y, zValue=1.0):  #common code
        if [x, y] in pointsAlreadyAdded:
            return
        pointsAlreadyAdded.append([x, y])
        graphicsItem = PointSelectionGraphicsItem(x - pointWid, y - pointWid,
                                                  2 * pointWid, 2 * pointWid)
        postProcessGraphicsItem(graphicsItem, {'x': x, 'y': y}, zValue)

    def addCircle(x, y, r, **extraKWs):
        graphicsItem = CircleSelectionGraphicsItem(x - r, y - r, 2 * r, 2 * r)
        KWs = {'x': x, 'y': y, 'r': r}
        KWs.update(extraKWs)
        postProcessGraphicsItem(graphicsItem, KWs,
                                zValue=1.01**-r)  #smaller circles on top

    def circlePoints(x, y, r):
        addSelectionPoint(x, y, 2)  #Circle center point
        addSelectionPoint(x + r, y, 2)  #Circle right quadrant point
        addSelectionPoint(x - r, y, 2)  #Circle left quadrant point
        addSelectionPoint(x, y + r, 2)  #Circle top quadrant point
        addSelectionPoint(x, y - r, 2)  #Circle bottom quadrant point

    for viewObject in viewObjects:
        if viewObject.ViewResult.strip() == '':
            continue
        XML_tree = SvgXMLTreeNode(viewObject.ViewResult, 0)
        scaling = XML_tree.scaling()
        SelectViewObjectPoint_loc = None
        for element in XML_tree.getAllElements():
            if element.tag == 'circle':
                x, y = element.applyTransforms(float(element.parms['cx']),
                                               float(element.parms['cy']))
                r = float(element.parms['r']) * scaling
                if doCircles:
                    addCircle(x, y, r)
                if doPoints:
                    circlePoints(x, y, r)

            if element.tag == 'text' and element.parms.has_key('x'):
                if doTextItems:
                    addSelectionPoint(*element.applyTransforms(
                        float(element.parms['x']), float(element.parms['y'])))
                elif doSelectViewObjectPoints:
                    addSelectionPoint(*element.applyTransforms(
                        float(element.parms['x']), float(element.parms['y'])))

            if element.tag == 'path':  #https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
                #print(element.XML)
                fitData = []
                dParmsXML = element.parms['d']
                #<spacing corrections>
                i = 0
                while i < len(dParmsXML) - 1:
                    if dParmsXML[i] in 'MmLlACcQZz,' and dParmsXML[
                            i + 1] in '-.0123456789':
                        dParmsXML = dParmsXML[:i + 1] + ' ' + dParmsXML[i + 1:]
                    i = i + 1
                #</spacing corrections>
                parms = dParmsXML.replace(',', ' ').strip().split()
                _pen_x = 0
                _pen_y = 0
                j = 0
                pathDescriptor = None
                while j < len(parms):
                    #print(parms[j:])
                    if parms[j] in list('MmLlACcQZz,'):
                        pathDescriptor = parms[j]
                    else:  #using previous pathDescriptor
                        if pathDescriptor == None:
                            raise RuntimeError, 'pathDescriptor == None! unable to parse path "%s" with d parms %s' % (
                                element.XML[element.pStart:element.pEnd],
                                parms)
                        parms.insert(
                            j,
                            pathDescriptor.replace('m', 'l').replace('M', 'L'))

                    if parms[j] == 'M' or parms[j] == 'm':
                        if parms[j] == 'M':
                            _pen_x, _pen_y = float(parms[j + 1]), float(
                                parms[j + 2])
                        else:
                            _pen_x = _pen_x + float(parms[j + 1])
                            _pen_y = _pen_y + float(parms[j + 2])
                        pen_x, pen_y = element.applyTransforms(_pen_x, _pen_y)
                        _path_start_x, _path_start_y = _pen_x, _pen_y
                        path_start_x, path_start_y = pen_x, pen_y
                        j = j + 3
                    elif parms[j] in ['L', 'l', 'Z', 'z']:
                        if parms[j] == 'L' or parms[j] == 'l':
                            if parms[j] == 'L':
                                _end_x, _end_y = float(parms[j + 1]), float(
                                    parms[j + 2])
                            else:
                                _end_x = _pen_x + float(parms[j + 1])
                                _end_y = _pen_y + float(parms[j + 2])
                            end_x, end_y = element.applyTransforms(
                                _end_x, _end_y)
                            j = j + 3
                        else:  #parms[j] == 'Z':
                            _end_x, _end_y = _path_start_x, _path_start_y
                            end_x, end_y = path_start_x, path_start_y
                            j = j + 1
                        if doPoints:
                            addSelectionPoint(pen_x, pen_y)
                            addSelectionPoint(end_x, end_y)
                        if doLines:
                            graphicsItem = LineSelectionGraphicsItem(
                                pen_x, pen_y, end_x, end_y)
                            postProcessGraphicsItem(graphicsItem, {
                                'x1': pen_x,
                                'y1': pen_y,
                                'x2': end_x,
                                'y2': end_y
                            })
                        if doMidPoints:
                            addSelectionPoint((pen_x + end_x) / 2,
                                              (pen_y + end_y) / 2)
                        _pen_x, _pen_y = _end_x, _end_y
                        pen_x, pen_y = end_x, end_y
                    elif parms[j] == 'A':
                        # The arc command begins with the x and y radius and ends with the ending point of the arc.
                        # Between these are three other values: x axis rotation, large arc flag and sweep flag.
                        rX, rY, xRotation, largeArc, sweep, _end_x, _end_y = map(
                            float, parms[j + 1:j + 1 + 7])
                        end_x, end_y = element.applyTransforms(_end_x, _end_y)
                        if doPoints:
                            addSelectionPoint(pen_x, pen_y)
                            addSelectionPoint(end_x, end_y)
                        if rX == rY:
                            _c_x, _c_y = findCircularArcCentrePoint(
                                rX, _pen_x, _pen_y, _end_x, _end_y,
                                largeArc == 1, sweep == 1
                            )  #do in untranformed co-ordinates as to preserve sweep flag
                            if not numpy.isnan(
                                    _c_x
                            ):  #if all went well findCircularArcCentrePoint
                                c_x, c_y = element.applyTransforms(_c_x, _c_y)
                                r = rX * scaling
                                if doCircles:
                                    #addCircle( c_x, c_y, r , largeArc=largeArc, sweep=sweep)
                                    gi = PathSelectionGraphicsItem()
                                    path = QtGui.QPainterPath(
                                        QtCore.QPointF(pen_x, pen_y))
                                    #path.arcTo(c_x - r, c_y -r , 2*r, 2*r, angle_1, angle_CCW) #dont know what is up with this function so trying something else.
                                    for _p in pointsAlongCircularArc(
                                            rX,
                                            _pen_x,
                                            _pen_y,
                                            _end_x,
                                            _end_y,
                                            largeArc == 1,
                                            sweep == 1,
                                            noPoints=12):
                                        path.lineTo(*element.applyTransforms(
                                            *_p))
                                    gi.setPath(path)
                                    postProcessGraphicsItem(
                                        gi, {
                                            'x': c_x,
                                            'y': c_y,
                                            'r': r,
                                            'largeArc': largeArc,
                                            'sweep': sweep,
                                        })
                                #if doPoints:
                                #    circlePoints( c_x, c_y, r)
                        _pen_x, _pen_y = _end_x, _end_y
                        pen_x, pen_y = end_x, end_y
                        j = j + 8
                    elif parms[j] == 'C' or parms[j] == 'c' or parms[
                            j] == 'Q':  #Bézier curve
                        if parms[j] == 'C' or parms[j] == 'c':
                            #cubic Bézier curve from the current point to (x,y) using
                            # (x1,y1) as the control point at the beginning of the curve and (x2,y2) as the control point at the end of the curve.
                            if parms[j] == 'C':
                                _x1, _y1, _x2, _y2, _end_x, _end_y = map(
                                    float, parms[j + 1:j + 1 + 6])
                            else:  #parms[j] == 'c':
                                _x1, _y1, _x2, _y2, _end_x, _end_y = numpy.array(
                                    map(float,
                                        parms[j + 1:j + 1 + 6])) + numpy.array(
                                            [_pen_x, _pen_y] * 3)
                            P = [[pen_x, pen_y],
                                 element.applyTransforms(_x1, _y1),
                                 element.applyTransforms(_x2, _y2),
                                 element.applyTransforms(_end_x, _end_y)]
                            j = j + 7
                        elif parms[
                                j] == 'Q':  # quadratic Bézier curve from the current point to (x,y) using (x1,y1) as the control point.
                            # Q (uppercase) indicates that absolute coordinates will follow;
                            # q (lowercase) indicates that relative coordinates will follow.
                            # Multiple sets of coordinates may be specified to draw a polybézier.
                            # At the end of the command, the new current point becomes the final (x,y) coordinate pair used in the polybézier.
                            _x1, _y1, _end_x, _end_y = map(
                                float, parms[j + 1:j + 1 + 4])
                            j = j + 5
                            P = [[pen_x, pen_y],
                                 element.applyTransforms(_x1, _y1),
                                 element.applyTransforms(_end_x, _end_y)]
                        if doFittedCircles or True:
                            x, y, r, r_error = fitCircle_to_path([P])
                            #print('fittedCircle: x, y, r, r_error', x, y, r, r_error)
                            if r_error < 10**-4:
                                gi = PathSelectionGraphicsItem()
                                path = QtGui.QPainterPath(
                                    QtCore.QPointF(pen_x, pen_y))
                                if len(P) == 4:
                                    path.cubicTo(QtCore.QPointF(*P[1]),
                                                 QtCore.QPointF(*P[2]),
                                                 QtCore.QPointF(*P[3]))
                                else:
                                    path.quadTo(QtCore.QPointF(*P[1]),
                                                QtCore.QPointF(*P[2]))
                                gi.setPath(path)
                                postProcessGraphicsItem(
                                    gi, {
                                        'x': x,
                                        'y': y,
                                        'r': r
                                    })

                        end_x, end_y = P[-1]
                        if doPoints:
                            addSelectionPoint(pen_x, pen_y)
                            addSelectionPoint(end_x, end_y)
                        #fitData.append( P )
                        _pen_x, _pen_y = _end_x, _end_y
                        pen_x, pen_y = end_x, end_y
                    else:
                        raise RuntimeError, 'unable to parse path "%s" with d parms %s' % (
                            element.XML[element.pStart:element.pEnd], parms)
                if j > 0 and doPathEndPoints:
                    addSelectionPoint(pen_x, pen_y)
                if j > 0 and doSelectViewObjectPoints and SelectViewObjectPoint_loc == None:
                    SelectViewObjectPoint_loc = pen_x, pen_y

            if element.tag == 'line':
                x1, y1 = element.applyTransforms(float(element.parms['x1']),
                                                 float(element.parms['y1']))
                x2, y2 = element.applyTransforms(float(element.parms['x2']),
                                                 float(element.parms['y2']))
                if doPoints:
                    addSelectionPoint(x1, y1)
                    addSelectionPoint(x2, y2)
                if doLines:
                    graphicsItem = LineSelectionGraphicsItem(x1, y1, x2, y2)
                    postProcessGraphicsItem(graphicsItem, {
                        'x1': x1,
                        'y1': y1,
                        'x2': x2,
                        'y2': y2
                    })
                if doMidPoints:
                    addSelectionPoint((x1 + x2) / 2, (y1 + y2) / 2)
                if doSelectViewObjectPoints and SelectViewObjectPoint_loc == None:  #second check to textElementes preference
                    SelectViewObjectPoint_loc = x2, y2

        if doSelectViewObjectPoints and SelectViewObjectPoint_loc <> None:
            addSelectionPoint(*SelectViewObjectPoint_loc)
            #if len(fitData) > 0:
            #    x, y, r, r_error = fitCircle_to_path(fitData)
            #    #print('fittedCircle: x, y, r, r_error', x, y, r, r_error)
            #    if r_error < 10**-4:
            #        if doFittedCircles:
            #            addCircle( x, y, r , r_error=r_error )
            #        if doPoints:
            #            circlePoints( x, y, r)

    return graphicItems
コード例 #13
0
def generateSelectionGraphicsItems(viewObjects,
                                   onClickFun,
                                   transform=None,
                                   sceneToAddTo=None,
                                   clearPreviousSelectionItems=True,
                                   doPoints=False,
                                   doTextItems=False,
                                   doLines=False,
                                   doCircles=False,
                                   doFittedCircles=False,
                                   doPathEndPoints=False,
                                   doMidPoints=False,
                                   doSelectViewObjectPoints=False,
                                   doEllipses=False,
                                   doArcCenters=True,
                                   pointWid=1.0,
                                   maskPen=defaultMaskPen,
                                   maskBrush=defaultMaskBrush,
                                   maskHoverPen=defaultMaskHoverPen):
    if clearPreviousSelectionItems:
        if sceneToAddTo <> None:
            for gi in sceneToAddTo.items():
                if isinstance(gi, CircleSelectionGraphicsItem):
                    sceneToAddTo.removeItem(gi)
        del graphicItems[:]

    def postProcessGraphicsItem(gi, elementParms, zValue=0.99):
        gi.setBrush(maskBrush)
        gi.setPen(maskPen)
        gi.selectionMaskPen = QtGui.QPen(maskPen)
        gi.selectionMaskHoverPen = QtGui.QPen(maskHoverPen)
        gi._onClickFun = onClickFun
        gi.elementParms = elementParms
        gi.elementXML = element  #should be able to get from functions name space
        gi.elementViewObject = viewObject
        gi.setAcceptHoverEvents(True)
        gi.setCursor(
            QtCore.Qt.CrossCursor
        )  # http://qt-project.org/doc/qt-5/qt.html#CursorShape-enum ; may not work for lines ...
        gi.setZValue(zValue)
        if transform <> None:
            gi.setTransform(transform)
        if sceneToAddTo <> None:
            sceneToAddTo.addItem(gi)
        graphicItems.append(gi)

    pointsAlreadyAdded = []

    def addSelectionPoint(x, y, zValue=1.0):  #common code
        if [x, y] in pointsAlreadyAdded:
            return
        pointsAlreadyAdded.append([x, y])
        graphicsItem = PointSelectionGraphicsItem(x - pointWid, y - pointWid,
                                                  2 * pointWid, 2 * pointWid)
        postProcessGraphicsItem(graphicsItem, {'x': x, 'y': y}, zValue)

    def addCircle(x, y, r, **extraKWs):
        graphicsItem = CircleSelectionGraphicsItem(x - r, y - r, 2 * r, 2 * r)
        KWs = {'x': x, 'y': y, 'r': r}
        KWs.update(extraKWs)
        postProcessGraphicsItem(graphicsItem, KWs,
                                zValue=1.01**-r)  #smaller circles on top

    def circlePoints(x, y, rx, ry):
        addSelectionPoint(x, y, 2)  #Circle/ellipse center point
        addSelectionPoint(x + rx, y, 2)  #Circle/ellipse right quadrant point
        addSelectionPoint(x - rx, y, 2)  #Circle/ellipse left quadrant point
        addSelectionPoint(x, y + ry, 2)  #Circle/ellipse top quadrant point
        addSelectionPoint(x, y - ry, 2)  #Circle/ellipse bottom quadrant point

    for viewObject in viewObjects:
        if not hasattr(viewObject, 'ViewResult'):
            continue
        if viewObject.ViewResult.strip() == '':
            continue
        DrawingsViews_info[viewObject.Name] = DrawingViewInfo(viewObject)
        viewInfo = DrawingsViews_info[viewObject.Name]  #shorthand
        XML_tree = SvgXMLTreeNode(viewObject.ViewResult, 0)
        scaling = XML_tree.scaling()
        viewInfo.scale = scaling
        SelectViewObjectPoint_loc = None
        for element in XML_tree.getAllElements():
            if element.tag == 'circle':
                x, y = element.applyTransforms(float(element.parms['cx']),
                                               float(element.parms['cy']))
                r = float(element.parms['r']) * scaling
                if doCircles:
                    addCircle(x, y, r)
                if doPoints:
                    circlePoints(x, y, r, r)
                viewInfo.updateBounds_ellipse(x, y, r, r)
            if element.tag == 'ellipse':
                cx, cy = element.applyTransforms(float(element.parms['cx']),
                                                 float(element.parms['cy']))
                rx, ry = float(element.parms['rx']) * scaling, float(
                    element.parms['ry']) * scaling
                if doCircles:
                    if rx == ry:
                        addCircle(cx, cy, rx)
                if doEllipses:
                    raise NotImplemented
                if doPoints:
                    circlePoints(cx, cy, rx, ry)
                viewInfo.updateBounds_ellipse(cx, cy, rx, ry)

            if element.tag == 'text' and element.parms.has_key('x'):
                if doTextItems:
                    addSelectionPoint(*element.applyTransforms(
                        float(element.parms['x']), float(element.parms['y'])))
                elif doSelectViewObjectPoints:
                    addSelectionPoint(*element.applyTransforms(
                        float(element.parms['x']), float(element.parms['y'])))

            if element.tag == 'path':
                path = SvgPath(element)
                for p in path.points:
                    if doPoints:
                        addSelectionPoint(p.x, p.y)
                    viewInfo.updateBounds(p.x, p.y)

                if doLines:
                    for line in path.lines:
                        x1, y1, x2, y2 = line.x1, line.y1, line.x2, line.y2
                        graphicsItem = LineSelectionGraphicsItem(
                            x1, y1, x2, y2)
                        postProcessGraphicsItem(graphicsItem, {
                            'x1': x1,
                            'y1': y1,
                            'x2': x2,
                            'y2': y2
                        })
                if doMidPoints:
                    for line in path.lines:
                        addSelectionPoint(*line.midPoint())
                for arc in path.arcs:
                    if doCircles or doEllipses:
                        if arc.circular:
                            gi = PathSelectionGraphicsItem()
                            gi.setPath(arc.QPainterPath())
                            postProcessGraphicsItem(
                                gi, {
                                    'x': arc.center[0],
                                    'y': arc.center[1],
                                    'r': arc.r * scaling,
                                    'arcPickle': pickle.dumps(arc)
                                })
                        elif doEllipses:
                            gi = PathSelectionGraphicsItem()
                            gi.setPath(arc.QPainterPath())
                            postProcessGraphicsItem(
                                gi, {
                                    'x': arc.center[0],
                                    'y': arc.center[1],
                                    'arcPickle': pickle.dumps(arc)
                                })
                    if doPoints and doArcCenters:
                        addSelectionPoint(arc.center[0], arc.center[1], 2)
                if doFittedCircles:
                    for bezierCurve in path.bezierCurves:
                        x, y, r, r_error = bezierCurve.fitCircle()
                        if r_error < 10**-4:
                            gi = PathSelectionGraphicsItem()
                            gi.setPath(bezierCurve.QPainterPath())
                            postProcessGraphicsItem(gi, {
                                'x': x,
                                'y': y,
                                'r': r
                            })
                if doPathEndPoints and len(path.points) > 0:
                    addSelectionPoint(path.points[-1].x, path.points[-1].y)
                if doSelectViewObjectPoints and SelectViewObjectPoint_loc == None and len(
                        path.points) > 0:
                    SelectViewObjectPoint_loc = path.points[-1].x, path.points[
                        -1].y

            if element.tag == 'line':
                x1, y1 = element.applyTransforms(float(element.parms['x1']),
                                                 float(element.parms['y1']))
                x2, y2 = element.applyTransforms(float(element.parms['x2']),
                                                 float(element.parms['y2']))
                if doPoints:
                    addSelectionPoint(x1, y1)
                    addSelectionPoint(x2, y2)
                viewInfo.updateBounds(x1, y1)
                viewInfo.updateBounds(x1, y2)

                if doLines:
                    graphicsItem = LineSelectionGraphicsItem(x1, y1, x2, y2)
                    postProcessGraphicsItem(graphicsItem, {
                        'x1': x1,
                        'y1': y1,
                        'x2': x2,
                        'y2': y2
                    })
                if doMidPoints:
                    addSelectionPoint((x1 + x2) / 2, (y1 + y2) / 2)
                if doSelectViewObjectPoints and SelectViewObjectPoint_loc == None:  #second check to textElementes preference
                    SelectViewObjectPoint_loc = x2, y2

        if doSelectViewObjectPoints and SelectViewObjectPoint_loc <> None:
            addSelectionPoint(*SelectViewObjectPoint_loc)
            #if len(fitData) > 0:
            #    x, y, r, r_error = fitCircle_to_path(fitData)
            #    #print('fittedCircle: x, y, r, r_error', x, y, r, r_error)
            #    if r_error < 10**-4:
            #        if doFittedCircles:
            #            addCircle( x, y, r , r_error=r_error )
            #        if doPoints:
            #            circlePoints( x, y, r, r)

    return graphicItems