Draft: importSVG.py, improved Pythonic style, 4 space indentation

This commit is contained in:
vocx-fc
2019-08-01 22:42:47 -05:00
committed by Yorik van Havre
parent 3d7995da71
commit 96046379be

View File

@@ -313,108 +313,108 @@ def transformCopyShape(shape, m):
def getsize(length, mode='discard', base=1):
"""Parse the length string containing number and unit.
"""Parse the length string containing number and unit.
Parameters
----------
length : str
The length is a string, including sign, exponential notation,
and unit: '+56215.14565E+6mm', '-23.156e-2px'.
mode : str, optional
One of 'discard', 'tuple', 'css90.0', 'css96.0', 'mm90.0', 'mm96.0'.
'discard' (default), it discards the unit suffix, and extracts
a number from the given string.
'tuple', return number and unit as a tuple
'css90.0', convert the unit to pixels assuming 90 dpi
'css96.0', convert the unit to pixels assuming 96 dpi
'mm90.0', convert the unit to millimeters assuming 90 dpi
'mm96.0', convert the unit to millimeters assuming 96 dpi
base : float, optional
A base to scale the length.
Parameters
----------
length : str
The length is a string, including sign, exponential notation,
and unit: '+56215.14565E+6mm', '-23.156e-2px'.
mode : str, optional
One of 'discard', 'tuple', 'css90.0', 'css96.0', 'mm90.0', 'mm96.0'.
'discard' (default), it discards the unit suffix, and extracts
a number from the given string.
'tuple', return number and unit as a tuple
'css90.0', convert the unit to pixels assuming 90 dpi
'css96.0', convert the unit to pixels assuming 96 dpi
'mm90.0', convert the unit to millimeters assuming 90 dpi
'mm96.0', convert the unit to millimeters assuming 96 dpi
base : float, optional
A base to scale the length.
Returns
-------
float
The numeric value of the length, as is, or transformed to
millimeters or pixels.
float, string
A tuple with the numeric value, and the unit if `mode='tuple'`.
"""
# Dictionaries to convert units to millimeters or pixels.
#
# The `em` and `ex` units are typographical units used in systems
# like LaTeX. Here the conversion factors are arbitrarily chosen,
# as they should depend on a specific font size used.
#
# The percentage factor is arbitrarily chosen, as it should depend
# on the viewport size or for filling patterns on the bounding box.
if mode == 'mm90.0':
tomm = {
'': 25.4/90, # default
'px': 25.4/90,
'pt': 1.25*25.4/90,
'pc': 15*25.4/90,
'mm': 1.0,
'cm': 10.0,
'in': 25.4,
'em': 15*2.54/90, #arbitrarily chosen; has to depend on font size
'ex': 10*2.54/90, #arbitrarily chosen; has to depend on font size
'%': 100 #arbitrarily chosen; has to depend on viewport size or (for filling patterns) on bounding box
}
if mode == 'mm96.0':
tomm = {
'': 25.4/96, # default
'px': 25.4/96,
'pt': 1.25*25.4/96,
'pc': 15*25.4/96,
'mm': 1.0,
'cm': 10.0,
'in': 25.4,
'em': 15*2.54/96, #arbitrarily chosen; has to depend on font size
'ex': 10*2.54/96, #arbitrarily chosen; has to depend on font size
'%': 100 #arbitrarily chosen; has to depend on viewport size or (for filling patterns) on bounding box
}
if mode == 'css90.0':
topx = {
'': 1.0, # default
'px': 1.0,
'pt': 1.25,
'pc': 15,
'mm': 90.0/25.4,
'cm': 90.0/254.0,
'in': 90,
'em': 15, #arbitrarily chosen; has to depend on font size
'ex': 10, #arbitrarily chosen; has to depend on font size
'%': 100 #arbitrarily chosen; has to depend on viewport size or (for filling patterns) on bounding box
}
if mode == 'css96.0':
topx = {
'': 1.0, # default
'px': 1.0,
'pt': 1.25,
'pc': 15,
'mm': 96.0/25.4,
'cm': 96.0/254.0,
'in': 96,
'em': 15, #arbitrarily chosen; has to depend on font size
'ex': 10, #arbitrarily chosen; has to depend on font size
'%': 100 #arbitrarily chosen; has to depend on viewport size or (for filling patterns) on bounding box
}
# Extract a number from a string like '+56215.14565E+6mm'
number, exponent, unit = re.findall('([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)(px|pt|pc|mm|cm|in|em|ex|%)?', length)[0]
if mode == 'discard':
return float(number)
elif mode == 'tuple':
return float(number), unit
elif mode == 'isabsolute':
return unit in ('mm', 'cm', 'in', 'px', 'pt')
elif mode == 'mm96.0' or mode == 'mm90.0':
return float(number) * tomm[unit]
elif mode == 'css96.0' or mode == 'css90.0':
if unit != '%':
return float(number) * topx[unit]
else:
return float(number) * base
Returns
-------
float
The numeric value of the length, as is, or transformed to
millimeters or pixels.
float, string
A tuple with the numeric value, and the unit if `mode='tuple'`.
"""
# Dictionaries to convert units to millimeters or pixels.
#
# The `em` and `ex` units are typographical units used in systems
# like LaTeX. Here the conversion factors are arbitrarily chosen,
# as they should depend on a specific font size used.
#
# The percentage factor is arbitrarily chosen, as it should depend
# on the viewport size or for filling patterns on the bounding box.
if mode == 'mm90.0':
tomm = {
'': 25.4/90, # default
'px': 25.4/90,
'pt': 1.25*25.4/90,
'pc': 15*25.4/90,
'mm': 1.0,
'cm': 10.0,
'in': 25.4,
'em': 15*2.54/90, #arbitrarily chosen; has to depend on font size
'ex': 10*2.54/90, #arbitrarily chosen; has to depend on font size
'%': 100 #arbitrarily chosen; has to depend on viewport size or (for filling patterns) on bounding box
}
if mode == 'mm96.0':
tomm = {
'': 25.4/96, # default
'px': 25.4/96,
'pt': 1.25*25.4/96,
'pc': 15*25.4/96,
'mm': 1.0,
'cm': 10.0,
'in': 25.4,
'em': 15*2.54/96, #arbitrarily chosen; has to depend on font size
'ex': 10*2.54/96, #arbitrarily chosen; has to depend on font size
'%': 100 #arbitrarily chosen; has to depend on viewport size or (for filling patterns) on bounding box
}
if mode == 'css90.0':
topx = {
'': 1.0, # default
'px': 1.0,
'pt': 1.25,
'pc': 15,
'mm': 90.0/25.4,
'cm': 90.0/254.0,
'in': 90,
'em': 15, #arbitrarily chosen; has to depend on font size
'ex': 10, #arbitrarily chosen; has to depend on font size
'%': 100 #arbitrarily chosen; has to depend on viewport size or (for filling patterns) on bounding box
}
if mode == 'css96.0':
topx = {
'': 1.0, # default
'px': 1.0,
'pt': 1.25,
'pc': 15,
'mm': 96.0/25.4,
'cm': 96.0/254.0,
'in': 96,
'em': 15, #arbitrarily chosen; has to depend on font size
'ex': 10, #arbitrarily chosen; has to depend on font size
'%': 100 #arbitrarily chosen; has to depend on viewport size or (for filling patterns) on bounding box
}
# Extract a number from a string like '+56215.14565E+6mm'
number, exponent, unit = re.findall('([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)(px|pt|pc|mm|cm|in|em|ex|%)?', length)[0]
if mode == 'discard':
return float(number)
elif mode == 'tuple':
return float(number), unit
elif mode == 'isabsolute':
return unit in ('mm', 'cm', 'in', 'px', 'pt')
elif mode == 'mm96.0' or mode == 'mm90.0':
return float(number) * tomm[unit]
elif mode == 'css96.0' or mode == 'css90.0':
if unit != '%':
return float(number) * topx[unit]
else:
return float(number) * base
def makewire(path, checkclosed=False, donttry=False):
@@ -508,105 +508,105 @@ def arccenter2end(center, rx, ry, angle1, angledelta, xrotation=0.0):
def arcend2center(lastvec, currentvec, rx, ry,
xrotation=0.0, correction=False):
'''Calculate the possible centers for an arc in endpoint parameterization.
'''Calculate the possible centers for an arc in endpoint parameterization.
Calculate (positive and negative) possible centers for an arc given in
``endpoint parametrization``.
See http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
Calculate (positive and negative) possible centers for an arc given in
``endpoint parametrization``.
See http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
the sweepflag is interpreted as: sweepflag <==> arc is travelled clockwise
the sweepflag is interpreted as: sweepflag <==> arc is travelled clockwise
Parameters
----------
lastvec : Base::Vector3
First point of the arc.
currentvec : Base::Vector3
End point (current) of the arc.
rx : float
Radius of the ellipse, semi-major axis in the X direction.
ry : float
Radius of the ellipse, semi-minor axis in the Y direction.
xrotation : float, optional
Default is 0. Rotation around the Z axis, in radians (CCW).
correction : bool, optional
Default is `False`. If it is `True`, the radii will be scaled
by a factor.
Parameters
----------
lastvec : Base::Vector3
First point of the arc.
currentvec : Base::Vector3
End point (current) of the arc.
rx : float
Radius of the ellipse, semi-major axis in the X direction.
ry : float
Radius of the ellipse, semi-minor axis in the Y direction.
xrotation : float, optional
Default is 0. Rotation around the Z axis, in radians (CCW).
correction : bool, optional
Default is `False`. If it is `True`, the radii will be scaled
by a factor.
Returns
-------
list, (float, float)
A tuple that consists of one list, and a tuple of radii.
[(positive), (negative)], (rx, ry)
The first element of the list is the positive tuple,
the second is the negative tuple.
[(Base::Vector3, float, float),
(Base::Vector3, float, float)], (float, float)
Types
[(vcenter+, angle1+, angledelta+),
(vcenter-, angle1-, angledelta-)], (rx, ry)
The first element of the list is the positive tuple,
consisting of center, angle, and angle increment;
the second element is the negative tuple.
'''
# scalefacsign = 1 if (largeflag != sweepflag) else -1
rx = float(rx)
ry = float(ry)
v0 = lastvec.sub(currentvec)
v0.multiply(0.5)
m1 = FreeCAD.Matrix()
m1.rotateZ(-xrotation) # eq. 5.1
v1 = m1.multiply(v0)
if correction:
eparam = v1.x**2 / rx**2 + v1.y**2 / ry**2
if eparam > 1:
eproot = math.sqrt(eparam)
rx = eproot * rx
ry = eproot * ry
denom = rx**2 * v1.y**2 + ry**2 * v1.x**2
numer = rx**2 * ry**2 - denom
results = []
Returns
-------
list, (float, float)
A tuple that consists of one list, and a tuple of radii.
[(positive), (negative)], (rx, ry)
The first element of the list is the positive tuple,
the second is the negative tuple.
[(Base::Vector3, float, float),
(Base::Vector3, float, float)], (float, float)
Types
[(vcenter+, angle1+, angledelta+),
(vcenter-, angle1-, angledelta-)], (rx, ry)
The first element of the list is the positive tuple,
consisting of center, angle, and angle increment;
the second element is the negative tuple.
'''
# scalefacsign = 1 if (largeflag != sweepflag) else -1
rx = float(rx)
ry = float(ry)
v0 = lastvec.sub(currentvec)
v0.multiply(0.5)
m1 = FreeCAD.Matrix()
m1.rotateZ(-xrotation) # eq. 5.1
v1 = m1.multiply(v0)
if correction:
eparam = v1.x**2 / rx**2 + v1.y**2 / ry**2
if eparam > 1:
eproot = math.sqrt(eparam)
rx = eproot * rx
ry = eproot * ry
denom = rx**2 * v1.y**2 + ry**2 * v1.x**2
numer = rx**2 * ry**2 - denom
results = []
# If the division is very small, set the scaling factor to zero,
# otherwise try to calculate it by taking the square root
if abs(numer/denom) < 10**(-1*(Draft.precision())):
scalefacpos = 0
else:
try:
scalefacpos = math.sqrt(numer/denom)
except ValueError:
FreeCAD.Console.PrintMessage('sqrt(%f/%f)\n' % (numer, denom))
scalefacpos = 0
# Calculate two values because the square root may be positive or negative
for scalefacsign in (1, -1):
scalefac = scalefacpos * scalefacsign
# Step2 eq. 5.2
vcx1 = Vector(v1.y*rx/ry, -v1.x*ry/rx, 0).multiply(scalefac)
m2 = FreeCAD.Matrix()
m2.rotateZ(xrotation)
centeroff = currentvec.add(lastvec)
centeroff.multiply(0.5)
vcenter = m2.multiply(vcx1).add(centeroff) # Step3 eq. 5.3
# angle1 = Vector(1, 0, 0).getAngle(Vector((v1.x - vcx1.x) / rx,
# (v1.y - vcx1.y) / ry,
# 0)) # F.6.5.5
# angledelta = Vector((v1.x - vcx1.x) / rx,
# (v1.y - vcx1.y) / ry,
# 0).getAngle(Vector((-v1.x - vcx1.x) / rx,
# (-v1.y - vcx1.y) / ry,
# 0)) # F.6.5.6
# we need the right sign for the angle
angle1 = DraftVecUtils.angle(Vector(1, 0, 0),
Vector((v1.x-vcx1.x)/rx,
# If the division is very small, set the scaling factor to zero,
# otherwise try to calculate it by taking the square root
if abs(numer/denom) < 10**(-1*(Draft.precision())):
scalefacpos = 0
else:
try:
scalefacpos = math.sqrt(numer/denom)
except ValueError:
FreeCAD.Console.PrintMessage('sqrt(%f/%f)\n' % (numer, denom))
scalefacpos = 0
# Calculate two values because the square root may be positive or negative
for scalefacsign in (1, -1):
scalefac = scalefacpos * scalefacsign
# Step2 eq. 5.2
vcx1 = Vector(v1.y*rx/ry, -v1.x*ry/rx, 0).multiply(scalefac)
m2 = FreeCAD.Matrix()
m2.rotateZ(xrotation)
centeroff = currentvec.add(lastvec)
centeroff.multiply(0.5)
vcenter = m2.multiply(vcx1).add(centeroff) # Step3 eq. 5.3
# angle1 = Vector(1, 0, 0).getAngle(Vector((v1.x - vcx1.x) / rx,
# (v1.y - vcx1.y) / ry,
# 0)) # F.6.5.5
# angledelta = Vector((v1.x - vcx1.x) / rx,
# (v1.y - vcx1.y) / ry,
# 0).getAngle(Vector((-v1.x - vcx1.x) / rx,
# (-v1.y - vcx1.y) / ry,
# 0)) # F.6.5.6
# we need the right sign for the angle
angle1 = DraftVecUtils.angle(Vector(1, 0, 0),
Vector((v1.x-vcx1.x)/rx,
(v1.y-vcx1.y)/ry,
0)) # eq. 5.5
angledelta = DraftVecUtils.angle(Vector((v1.x-vcx1.x)/rx,
(v1.y-vcx1.y)/ry,
0)) # eq. 5.5
angledelta = DraftVecUtils.angle(Vector((v1.x-vcx1.x)/rx,
(v1.y-vcx1.y)/ry,
0),
Vector((-v1.x-vcx1.x)/rx,
(-v1.y-vcx1.y)/ry,
0)) # eq. 5.6
results.append((vcenter, angle1, angledelta))
return results, (rx, ry)
0),
Vector((-v1.x-vcx1.x)/rx,
(-v1.y-vcx1.y)/ry,
0)) # eq. 5.6
results.append((vcenter, angle1, angledelta))
return results, (rx, ry)
def getrgb(color):