forked from hamish2014/FreeCAD_drawing_dimensioning
/
angularDimension.py
179 lines (162 loc) · 8.07 KB
/
angularDimension.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# This Python file uses the following encoding: utf-8
from dimensioning import *
import selectionOverlay, previewDimension
from dimensionSvgConstructor import *
d = DimensioningProcessTracker()
def angularDimensionSVG( line1, line2, x_baseline, y_baseline, x_text=None, y_text=None,
textFormat_angular='%3.1f°', comma_decimal_place=False, gap_datum_points = 2, dimension_line_overshoot=1, arrowL1=3, arrowL2=1, arrowW=2, strokeWidth=0.5, lineColor='blue', arrow_scheme='auto',
textRenderer=defaultTextRenderer):
XML = []
x_int, y_int = lineIntersection(line1, line2)
#XML.append( '<circle cx ="%f" cy ="%f" r="4" stroke="none" fill="rgb(0,0,255)" /> ' % (x_int, y_int) ) #for debugging
p_center = numpy.array([ x_int, y_int ] )
p1 = numpy.array( [line1[0], line1[1]] )
p2 = numpy.array( [line1[2], line1[3]] )
p3 = numpy.array( [line2[0], line2[1]] )
p4 = numpy.array( [line2[2], line2[3]] )
p5 = numpy.array([ x_baseline, y_baseline ])
r_P5 = norm( p5 -p_center )
# determine arrow position
def arrowPosition( d ):
cand1 = p_center + d*r_P5
cand2 = p_center - d*r_P5
return cand1 if norm( cand1 - p5) < norm( cand2 - p5) else cand2
p_arrow1 = arrowPosition(directionVector(p1,p2))
p_arrow2 = arrowPosition(directionVector(p3,p4))
def line_to_arrow_point( a, b, c): # where a=p1,b=p2 or a=p3,b=p4 and c=p_arrow1 or c=p_arrow2
if abs( norm(a -b) - (norm(a-c) + norm(b-c))) < norm(a -b)/1000:
return
s = a if norm(a-c) < norm(b-c) else b #start_point
d = directionVector( s, c)
v = s + gap_datum_points*d
w = c + dimension_line_overshoot*d
XML.append( svgLine(v[0],v[1],w[0],w[1], lineColor, strokeWidth) )
line_to_arrow_point( p1, p2, p_arrow1)
line_to_arrow_point( p3, p4, p_arrow2)
d1 = directionVector(p_center, p_arrow1)
d2 = directionVector(p_center, p_arrow2)
largeArc = False # given the selection method for the arrow heads (points and line1 and line2 used for measuring the angle)
angle_1 = arctan2( d2[1], d2[0] )
angle_2 = arctan2( d1[1], d1[0] )
if abs(angle_1 - angle_2) < pi: #modulo correction required, since arctan2 return [-pi, pi]
if angle_2 < angle_1:
angle_2 = angle_2 + 2*pi
else:
angle_1 = angle_1 + 2*pi
sweep = angle_2 > angle_1
#rX, rY, xRotation, largeArc, sweep, _end_x, _end_y =
XML.append('<path d = "M %f %f A %f %f 0 %i %i %f %f" style="stroke:%s;stroke-width:%1.2f;fill:none" />' % (p_arrow1[0],p_arrow1[1], r_P5, r_P5, largeArc, sweep, p_arrow2[0],p_arrow2[1],lineColor, strokeWidth))
if arrow_scheme <> 'off': #then draw arrows
if arrow_scheme == 'auto':
s = 1 if angle_2 > angle_1 else -1
elif arrow_scheme == 'in':
s = 1
elif arrow_scheme == 'out':
s = -1
XML.append( arrowHeadSVG( p_arrow1, rotate2D(d1, s*pi/2), arrowL1, arrowL2, arrowW, lineColor ) )
XML.append( arrowHeadSVG( p_arrow2, rotate2D(d2,-s*pi/2), arrowL1, arrowL2, arrowW, lineColor ) )
if x_text <> None and y_text <> None:
v = arccos( numpy.dot(d1, d2) )/ pi * 180
textRotation = numpy.arctan2( y_text - y_int, x_text - x_int)
textXML = textRenderer( x_text, y_text, dimensionText(v,textFormat_angular, comma=comma_decimal_place), textRotation)
XML.append( textXML )
return '<g> %s </g>' % '\n'.join(XML)
d.registerPreference( 'textFormat_angular', '%3.1f°', 'format mask')
d.registerPreference( 'arrow_scheme')
d.registerPreference( 'comma_decimal_place' )
d.registerPreference( 'gap_datum_points')
d.registerPreference( 'dimension_line_overshoot')
d.registerPreference( 'arrowL1')
d.registerPreference( 'arrowL2')
d.registerPreference( 'arrowW')
d.registerPreference( 'strokeWidth' )
d.registerPreference( 'lineColor' )
d.registerPreference( 'textRenderer' )
def angularDimension_points_preview(mouseX, mouseY):
args = d.args + [ mouseX, mouseY ] if len(d.args) < 6 else d.args
return angularDimensionSVG( *args, **d.dimensionConstructorKWs )
def angularDimension_points_clickHandler( x, y ):
d.args = d.args + [ x, y ]
d.stage = d.stage + 1
if d.stage == 4 :
return 'createDimension:%s' % findUnusedObjectName('dim')
def selectFun( event, referer, elementXML, elementParms, elementViewObject ):
referer.lockSelection()
if isinstance(referer, selectionOverlay.LineSelectionGraphicsItem):
x1,y1,x2,y2 = [ elementParms[k] for k in [ 'x1', 'y1', 'x2', 'y2' ] ]
debugPrint(2, 'selecting line %i with x1=%3.1f y1=%3.1f, x2=%3.1f y2=%3.1f' % (d.stage, x1,y1,x2,y2) )
if d.stage == 0: #then select line1
d.args = [ [x1,y1,x2,y2] ]
d.stage = 1
for gi in selectionOverlay.graphicItems:
if isinstance(gi, selectionOverlay.PointSelectionGraphicsItem):
gi.hide()
else:
d.args = d.args + [[x1,y1,x2,y2]]
d.stage = 2
selectionOverlay.hideSelectionGraphicsItems()
previewDimension.initializePreview( d, angularDimension_points_preview, angularDimension_points_clickHandler )
else: #user selecting 3 points
x, y = elementParms['x'], elementParms['y']
debugPrint(2, 'point %i selected at x=%3.1f y=%3.1f' %(d.stage +1,x,y))
if d.stage == 0:
d.pointStart = x,y
d.stage = 1
for gi in selectionOverlay.graphicItems:
if isinstance(gi, selectionOverlay.LineSelectionGraphicsItem):
gi.hide()
elif d.stage == 1:
d.pointCenter = x,y
d.stage = 2
else:
x_c, y_c = d.pointCenter
x1, y1 = d.pointStart
x2, y2 = x,y
d.args = [ [x_c, y_c, x1, y1], [x_c, y_c, x2, y2] ]
d.stage = 2 #hack to allow intergation with dim from 2 line code
selectionOverlay.hideSelectionGraphicsItems()
previewDimension.initializePreview( d, angularDimension_points_preview, angularDimension_points_clickHandler)
#selection variables for angular dimensioning
line_maskPen = QtGui.QPen( QtGui.QColor(0,255,0,100) )
line_maskPen.setWidth(2.0)
line_maskHoverPen = QtGui.QPen( QtGui.QColor(0,255,0,255) )
line_maskHoverPen.setWidth(2.0)
line_maskBrush = QtGui.QBrush() #clear
point_maskBrush = QtGui.QBrush( QtGui.QColor(0,160,0,100) )
point_maskPen = QtGui.QPen( QtGui.QColor(0,160,0,100) )
point_maskPen.setWidth(0.0)
point_maskHoverPen = QtGui.QPen( QtGui.QColor(0,255,0,255) )
point_maskHoverPen.setWidth(0.0)
class AngularDimension:
def Activated(self):
V = getDrawingPageGUIVars()
d.activate(V, dialogTitle='Add Angular Dimension', dialogIconPath=os.path.join( iconPath , 'angularDimension.svg' ), endFunction=self.Activated )
selectionOverlay.generateSelectionGraphicsItems(
[obj for obj in V.page.Group if not obj.Name.startswith('dim')],
selectFun ,
transform = V.transform,
sceneToAddTo = V.graphicsScene,
doLines=True,
maskPen= line_maskPen,
maskHoverPen= line_maskHoverPen,
maskBrush = line_maskBrush
)
selectionOverlay.generateSelectionGraphicsItems(
[obj for obj in V.page.Group if not obj.Name.startswith('dim')],
selectFun ,
transform = V.transform,
sceneToAddTo = V.graphicsScene,
doPoints=True,
maskPen= point_maskPen,
maskHoverPen= point_maskHoverPen,
maskBrush = point_maskBrush, #clear
clearPreviousSelectionItems = False,
)
selectionOverlay.addProxyRectToRescaleGraphicsSelectionItems( V.graphicsScene, V.graphicsView, V.width, V.height)
def GetResources(self):
return {
'Pixmap' : os.path.join( iconPath , 'angularDimension.svg' ) ,
'MenuText': 'Angular Dimension',
'ToolTip': 'Creates a angular dimension'
}
FreeCADGui.addCommand('dd_angularDimension', AngularDimension())