# Procedures to group ratser filling elements in various ways. # Last edited on 2021-06-04 05:48:22 by jstolfi import raster_regroup_IMP # The procedures in this module assume that the parameter {OPHS} is a # list of oriented paths that are elements of a solid fill, each # possibly assigned to a /group/ whose index is accessed through # {path_hp.get_group}. The procedures split or redefine those groups # into new groups according to various criteria, and attach the new # group indices to the paths of {OPHS} with {path_hp.set_group}. # # Each path in {OPHS} should consist of a single raster trace. The paths # must be pairwise disjoint and all parallel to some unit direction # vector {xdir}. They must be sorted in /scanline order/, which is # defined by increasing projection on an axis {ydir} perpendicular to # {xdir}, ignoring roundoff errors; with ties broken by increasing # projection along {xdir}. The orientations of the paths and traces are # ignored by these procedures. # # These procedures use the contact information of each path as # accessed by {path_hp.get_contacts} and {path_hp.set_contacts}. # These lists must have all contacts which have both sides # on paths of {OPHS}, and only those. Contacts between {OPHS} and # other paths (such as contours) should not be in those lists. # # Every procedure that is supposed to change the current group # assignments, such as {split_at_forks} or {split_by_size}, will # renumber the new groups with consecutive integers starting at 0, even # if the partition of {OPHS} into groups remains the same. They return # the number of new groups created. def merge_all(OPHS): # Ignores the current group assignments of the paths in {OPHS}, and reassigns # all to group 0. return raster_regroup_IMP.merge_all(OPHS) def by_contours(OPHS, OCRS): # Ignores the current group assignment and instead separates the filler # elements from {OPHS} into new groups, one for each contour (closed # oriented path) in the list {OCRS}. Each filler will be assigned to # the group with index {icr} such that {ocr=OCRS[icr]} is the # innermost contour that contains it. # # It is assumed that all fillers are in the interior of the slice. # Therefore, there will not be any filler assigned to a group index # {icr} if {icr >= len(OCRS)}, if {OCRS[icr]} is an inner (hole) # contour, or if contour {OCRS[icr]} is an outer contour but there is # no filler inside it except inside nested contours. return raster_regroup_IMP.by_contours(OPHS, OCRS) def split_at_forks(OPHS): # Splits the current groups of fillers from {OPHS} into maximal # sub-groups connected by single contacts. # # Specifically, each of the original groups is split into maximal # sub-groups such that, in every sub-group whose fillers are # {GPH[0..m-1]}, and for every {i} in {1..m-1}, there is a contact # between {GPH[i-1]} and {GPH[i]}, which is the only contact on the # upper side of {GPH[i-1]} and the only contact on the lower side of # {GPH[i]} return raster_regroup_IMP.split_at_forks(OPHS) def split_by_size(OPHS, ydir, max_lines): # Splits each current group, if needed, into sug-groups with at most # {max_lines} whole scan-lines each. # # In particular, if {max_lines} is 1, each new group will be contained # in a single scan-line. If that operation is applied after # {split_at_forks} each group will be a single filler element. raster_regroup_IMP.split_by_size(OPHS, ydir, max_lines)