# Tools for raster fillings. # Last edited on 2021-09-30 13:08:58 by stolfi import raster_IMP import path # A /raster fill element/ is a path consisting of a single move which is # a trace. A /raster filling/ is a collection of raster fill elements of # the same width {wd} that are all parallel to some direction {xdir}, # and whose positions along the perpendicular direction {ydir} are all # approximately integer multiples of {wd} plus some arbitrary shift, the # /scanline phase/. def get_spacing_and_phase(OPHS, xdir, ydir): # Given a list {OPHS} of filler elements, in arbtrary order, returns # estimtes of the average scanline spacing {ystep} (which should be # approximately the common trace width) and scanline phase {yphase}. # # The phase should be the approximate {ydir} projection of the # lowest scanline in direction {ydir}. # # Fails if the list is empty, or if the elements are not a proper raster # fill. return raster_IMP.get_spacing_and_phase(OPHS, xdir, ydir) def scanline_index(oph, xdir, ydir, ystep, yphase): # Returns the index of the scanline that contains the raster fill element {oph}. # Assumes that the scanline projections in the {ydir} direction are # approximately {yphase + isc*ystep}. return raster_IMP.scanline_index(oph, xdir, ydir, ystep, yphase) def sort_by_scanline(OPHS, xdir, ydir, ystep, yphase): # Given a list {OPHS} of filler elements, in arbtrary order, returns a # copy of the list with the same rasters sorted by increasing scanline # order. Assumes that the rasters are parallel to the unit vector {xdir}, # and that the projecttion of scanline with index {isc} on the perpendicular # direction {ydir} is approximately {yphase + isc*ystep}. return raster_IMP.sort_by_scanline(OPHS, xdir, ydir, ystep, yphase) def separate_by_scanline(OPHS, xdir, ydir, ystep, yphase): # Given a list {OPHS} of filler elements, in scanline order, returns a # list {SCS} of sub-lists, wehere each sub-list {SCS[isc]} contains # the indics into {OPHS} of the fillers on the scan-line with index # {isc}, also in scan-line order. # # Assumes that the rasters are parallel to the unit vector {xdir}; # that the projection of scanline with index {isc} on the # perpendicular direction {ydir} is approximately {yphase + # isc*ystep}; and that the scanline indices are all non-negative. return raster_IMP.separate_by_scanline(OPHS, xdir, ydir, ystep, yphase) def make_raster_raster_link(oph0, oph1, mp_link, name): # Creates a link path betwen the initial points of the fill elements # {oph0} and {oph1}. Attaches the link to the lists of links of the # two paths with {raster_hp.add_link}. # # The link path consists of a single trace with parameters {mp_link} # The trace will be named "T{name}" and the path "P{name}". # # The link is created only if the two traces satisfy the conditions # of {move.connector}, otherwise the procedure does nothing. # Usually, that means {oph0} and {oph1} are parallel and oriented in # the same direction. # # The procedure returns the created link, or {None} if it was not created. return raster_IMP.make_raster_raster_link(oph0, oph1, mp_link, name) def create_all_raster_raster_links(OPHS, xdir, ydir, mp_link): # Given a list {OPHS} of raster fill elements, in arbitrary order, # creates link paths between endpoints of rasters in adjacent # scanlines, when appropriate. Returns a list of those link paths. # # Specifically, the procedure calls {make_raster_raster_link} for any # two rasters {oph0,oph1} in consecutive scanlines. # return raster_IMP.create_all_raster_raster_links(OPHS, xdir, ydir, mp_link) def create_all_raster_raster_contacts(OPHS, xdir, ydir): # Given a list {OPHS} of raster fill elements, in arbitrary order, # creates contacts between rasters in adjacent # scanlines that have significant length of shared border. # Returns a list of those contacts. # # The procedure also attaches the contact to the lists of contacts # of the two paths, with {path_hp.add_contact}. # return raster_IMP.create_all_raster_raster_contacts(OPHS, xdir, ydir) def endpoints_from_shape(S, B, xdir, ydir, ystep, yphase): # Computes the endpoints of raster lines from a description {S} of the # filling region {D}. # # The result is a list {PTRS} such that {PTRS[i][j][k]} is endpoint # {k} (0=left, 1=right) of raster {j} on scan-line {i} from bottom. # # The argument {S} must be a two-dimensional {RootRay_Shape} object. It is implicitly # intersected with the box {B}. # # The scan lines are parallel to the direction {xdir} and spaced in # the direction {ydir} by {ystep}. The axis of one of the scan-lines # passes through the point {yphase*ydir}. All scan-lines that cross # the box {B} will be considered. # # The rasters will be oriented the direction {xdir}. They will be # sorted by projction on {ydir} and ties brokem by projection on # {xdir} # return raster_IMP.endpoints_from_shape(S, B, xdir, ydir, ystep, yphase) def from_endpoints(PTRS, mp): # Creates a list {OPHS} of paths, each a single raster line, from the endpoints in {PTRS}. # # The parameter {PTRS} should be a list such that {PTRS[i][j][k]} is endpoint # {k} (0=left, 1=right) of raster {j} on scan-line {i} from bottom # # The result {OPHS} of paths, each a single raster line with the given endpoinst # and {MoveParms} parameter record {mp}. # # Also calls {path.clear_links} and {path_hp.clear_contacts} for each raster element. return raster_IMP.from_endpoints(PTRS, mp)