kopia lustrzana https://github.com/evil-mad/EggBot
Issue 33. Will checkin fix for eggbot.py after I have a chance to do some drawing this evening. However, same fix seems to work for hatching
git-svn-id: https://eggbotcode.googlecode.com/svn/trunk@176 72233254-1b6c-9e9c-5072-401df62706fbpull/47/head
rodzic
336625dca6
commit
f200a9a6bc
|
@ -85,7 +85,9 @@ import cubicsuperpath
|
|||
import cspsubdiv
|
||||
import bezmisc
|
||||
import math
|
||||
#import time
|
||||
|
||||
N_PAGE_WIDTH = 3200
|
||||
N_PAGE_HEIGHT = 800
|
||||
|
||||
'''
|
||||
Geometry 101: Determing if two lines intersect
|
||||
|
@ -338,6 +340,31 @@ def inverseTransform ( tran ):
|
|||
[-tran[1][0]/D, tran[0][0]/D,
|
||||
(tran[1][0]*tran[0][2] - tran[0][0]*tran[1][2])/D]]
|
||||
|
||||
def parseLengthWithUnits( str ):
|
||||
|
||||
'''
|
||||
Parse an SVG value which may or may not have units attached
|
||||
This version is greatly simplified in that it only allows: no units,
|
||||
units of px, and units of %. Everything else, it returns None for.
|
||||
There is a more general routine to consider in scour.py if more
|
||||
generality is ever needed.
|
||||
'''
|
||||
|
||||
u = 'px'
|
||||
s = str.strip()
|
||||
if s[-2:] == 'px':
|
||||
s = s[:-2]
|
||||
elif s[-1:] == '%':
|
||||
u = '%'
|
||||
s = s[:-1]
|
||||
|
||||
try:
|
||||
v = float( s )
|
||||
except:
|
||||
return None, None
|
||||
|
||||
return v, u
|
||||
|
||||
# Lifted with impunity from eggbot.py
|
||||
|
||||
def subdivideCubicPath( sp, flat, i=1 ):
|
||||
|
@ -394,7 +421,7 @@ class Eggbot_Hatch( inkex.Effect ):
|
|||
def __init__( self ):
|
||||
|
||||
inkex.Effect.__init__( self )
|
||||
#self.t0 = time.clock()
|
||||
|
||||
self.xmin, self.ymin = ( float( 0 ), float( 0 ) )
|
||||
self.xmax, self.ymax = ( float( 0 ), float( 0 ) )
|
||||
self.paths = {}
|
||||
|
@ -402,6 +429,13 @@ class Eggbot_Hatch( inkex.Effect ):
|
|||
self.hatches = {}
|
||||
self.transforms = {}
|
||||
|
||||
# For handling an SVG viewbox attribute, we will need to know the
|
||||
# values of the document's <svg> width and height attributes as well
|
||||
# as establishing a transform from the viewbox to the display.
|
||||
self.docWidth = float( N_PAGE_WIDTH )
|
||||
self.docHeight = float( N_PAGE_HEIGHT )
|
||||
self.docTransform = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
|
||||
|
||||
self.OptionParser.add_option(
|
||||
"--crossHatch", action="store", dest="crossHatch",
|
||||
type="inkbool", default=False,
|
||||
|
@ -415,6 +449,61 @@ class Eggbot_Hatch( inkex.Effect ):
|
|||
dest="hatchSpacing", default=10.0,
|
||||
help="Spacing between hatch lines" )
|
||||
|
||||
def getLength( self, name, default ):
|
||||
|
||||
'''
|
||||
Get the <svg> attribute with name "name" and default value "default"
|
||||
Parse the attribute into a value and associated units. Then, accept
|
||||
no units (''), units of pixels ('px'), and units of percentage ('%').
|
||||
'''
|
||||
|
||||
str = self.document.getroot().get( name )
|
||||
if str:
|
||||
v, u = parseLengthWithUnits( str )
|
||||
if not v:
|
||||
# Couldn't parse the value
|
||||
return None
|
||||
elif ( u == '' ) or ( u == 'px' ):
|
||||
return v
|
||||
elif u == '%':
|
||||
return float( default ) * v / 100.0
|
||||
else:
|
||||
# Unsupported units
|
||||
return None
|
||||
else:
|
||||
# No width specified; assume the default value
|
||||
return float( default )
|
||||
|
||||
def getDocProps( self ):
|
||||
|
||||
'''
|
||||
Get the document's height and width attributes from the <svg> tag.
|
||||
Use a default value in case the property is not present or is
|
||||
expressed in units of percentages.
|
||||
'''
|
||||
|
||||
self.docHeight = self.getLength( 'height', N_PAGE_HEIGHT )
|
||||
self.docWidth = self.getLength( 'width', N_PAGE_WIDTH )
|
||||
if ( self.docHeight == None ) or ( self.docWidth == None ):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def handleViewBox( self ):
|
||||
|
||||
'''
|
||||
Set up the document-wide transform in the event that the document has an SVG viewbox
|
||||
'''
|
||||
|
||||
viewbox = self.document.getroot().get( 'viewBox' )
|
||||
if viewbox:
|
||||
if self.getDocProps():
|
||||
vinfo = viewbox.strip().replace( ',', ' ' ).split( ' ' )
|
||||
if ( vinfo[2] != 0 ) and ( vinfo[3] != 0 ):
|
||||
sx = self.docWidth / float( vinfo[2] )
|
||||
sy = self.docHeight / float( vinfo[3] )
|
||||
self.docTransform = simpletransform.parseTransform( 'scale(%f,%f)' % (sx, sy) )
|
||||
|
||||
def addPathVertices( self, path, node=None, transform=None ):
|
||||
|
||||
'''
|
||||
|
@ -443,7 +532,7 @@ class Eggbot_Hatch( inkex.Effect ):
|
|||
return
|
||||
|
||||
# Apply any transformation
|
||||
if transform:
|
||||
if transform != None:
|
||||
simpletransform.applyTransformToPath( transform, p )
|
||||
|
||||
# Now traverse the simplified path
|
||||
|
@ -742,7 +831,7 @@ class Eggbot_Hatch( inkex.Effect ):
|
|||
inkex.errormsg( 'Warning: unable to draw object <%s>, please convert it to a path first.' % node.tag )
|
||||
pass
|
||||
|
||||
def joinFillsWithNode ( self, node, path ):
|
||||
def joinFillsWithNode ( self, node, stroke_width, path ):
|
||||
|
||||
'''
|
||||
Generate a SVG <path> element containing the path data "path".
|
||||
|
@ -765,7 +854,7 @@ class Eggbot_Hatch( inkex.Effect ):
|
|||
|
||||
# Now make a <path> element which contains the hatches & is a child
|
||||
# of the new <g> element
|
||||
style = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': '1' }
|
||||
style = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': '%f' % stroke_width}
|
||||
line_attribs = { 'style':simplestyle.formatStyle( style ), 'd': path }
|
||||
tran = node.get( 'transform' )
|
||||
if ( tran != None ) and ( tran != '' ):
|
||||
|
@ -846,18 +935,21 @@ class Eggbot_Hatch( inkex.Effect ):
|
|||
|
||||
def effect( self ):
|
||||
|
||||
# Viewbox handling
|
||||
self.handleViewBox()
|
||||
|
||||
# Build a list of the vertices for the document's graphical elements
|
||||
if self.options.ids:
|
||||
# Traverse the selected objects
|
||||
for id in self.options.ids:
|
||||
self.recursivelyTraverseSvg( [self.selected[id]] )
|
||||
self.recursivelyTraverseSvg( [self.selected[id]], self.docTransform )
|
||||
else:
|
||||
# Traverse the entire document
|
||||
self.recursivelyTraverseSvg( self.document.getroot() )
|
||||
self.recursivelyTraverseSvg( self.document.getroot(), self.docTransform )
|
||||
|
||||
# Build a grid of possible hatch lines
|
||||
self.makeHatchGrid( float( self.options.hatchAngle ),
|
||||
float( self.options.hatchSpacing ), True )
|
||||
float( self.options.hatchSpacing ), True )
|
||||
if self.options.crossHatch:
|
||||
self.makeHatchGrid( float( self.options.hatchAngle + 90.0 ),
|
||||
float( self.options.hatchSpacing ), False )
|
||||
|
@ -872,13 +964,26 @@ class Eggbot_Hatch( inkex.Effect ):
|
|||
# pointer as the dictionary key under which to save the hatch
|
||||
# fills for that node.
|
||||
|
||||
s = 1 / math.sqrt(2)
|
||||
for key in self.hatches:
|
||||
path = ''
|
||||
direction = True
|
||||
if self.transforms.has_key( key ):
|
||||
transform = inverseTransform( self.transforms[key] )
|
||||
# Determine the scaled stroke width for a hatch line
|
||||
# We produce a line segment of unit length, transform
|
||||
# its endpoints and then determine the length of the
|
||||
# resulting line segment.
|
||||
pt1 = [0, 0]
|
||||
pt2 = [s, s]
|
||||
simpletransform.applyTransformToPoint( transform, pt1 )
|
||||
simpletransform.applyTransformToPoint( transform, pt2 )
|
||||
dx = pt2[0] - pt1[0]
|
||||
dy = pt2[1] - pt1[1]
|
||||
stroke_width = math.sqrt( dx * dx + dy * dy )
|
||||
else:
|
||||
transform = None
|
||||
stroke_width = float( 1.0 )
|
||||
for segment in self.hatches[key]:
|
||||
pt1 = segment[0]
|
||||
pt2 = segment[1]
|
||||
|
@ -909,7 +1014,7 @@ class Eggbot_Hatch( inkex.Effect ):
|
|||
path += 'M %f,%f l %f,%f ' % \
|
||||
( pt2[0], pt2[1], pt1[0] - pt2[0], pt1[1] - pt2[1] )
|
||||
direction = not direction
|
||||
self.joinFillsWithNode( key, path[:-1] )
|
||||
self.joinFillsWithNode( key, stroke_width, path[:-1] )
|
||||
|
||||
#inkex.errormsg("Elapsed CPU time was %f" % (time.clock()-self.t0))
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue