# HotPath-related path attributes. # Last edited on 2021-06-02 23:24:34 by jstolfi import path_hp_IMP import path import move import contact import block # In addition to the fields defined in the {path} module, each {Path} # object also has some additional fields that are used during the # {hotpath.best_path} algorithm. This module gives access to those # attributes. # # These attributes are not defined automatically. Their initial values # are undefined and must be properly defined by the {set_*} procedures # below, just before or during the heuristic. # # Most of these procedures take an oriented path parameter {oph} for convenience, but # the fields are associated with the underlying {Path} object and therefore # they are automatically shared by {oph} and {path.rev(oph)}. The orientation # of {oph} may however affect how the information is stored or retrieved. # However those fields are not shared by new paths derived from {oph}, e. g. # through {path.concat}, {path.displace}, or {path.shift_contour}. # PATH CONTACTS # Each {Path} object {ph} may have two lists of {Contact} objects # assigned to it accesded with {get_contacts(oph,i)} below. When reading # a set of raster-type filling elements, the two lists are the contacts # with the rasters on the scanline "below" it and with those on the # scanline "above" it, respectively, for a specified "up" direction. def clear_contacts(oph): # Clears the contact lists associated with the underlying {Path} # object of the oriented path {oph}. return path_hp_IMP.clear_contacts(oph) def get_contacts(oph, i): # Returns the list of contacts on side {i} of the {Path} object # underlying {oph}, as assigned by {add_contact}. return path_hp_IMP.get_contacts(oph, i) def add_contact(oph, i, ct): # Appends {ct} to the list of contacts on side {i} of {oph}. # The list must have been initialized previously by {clear_contacts}. path_hp_IMP.add_contact(oph, i, ct) # OWNING BLOCK # Each {Path} object {ph} can be assigned a {Block} object {bc}. During # the tool-path construction algorithms, for example, the block {bc} is # such that {choice(bc,ich)} is {ph} or its reversal, for at least one # index {ich}. def get_block(oph): # Returns the /owning block/ of the {Path} object underlying the # oriented path {oph}. return path_hp_IMP.get_block(oph) def set_block(oph, bc): # Sets the owning block of the {Path} object underlying {oph} to {bc}. # See {get_block} above. path_hp_IMP.set_block(oph, bc) # LINK PATHS # Each path {oph} that is a candidate filling element can have a set of # precomputed link paths that can be used to connect it to other # candidate filling paths. These links are associated to the endpoints # of the underlying {Path} object of {oph} by {clear_links} and # {add_link} below. The orientation of the path {oph} is used only to # determine which endpoint the links are supposed to connect to. def clear_links(oph): # Sets the link lists of the path {oph} to empty. path_hp_IMP.clear_links(oph) def add_link(oph, olk): # Appends the oriented link path {olk} to the list of # links associated with {oph}'s underlying {Path} object. # The link path must end at {pini(oph)}. path_hp_IMP.add_link(oph, olk) def set_links(oph, OLKS): # Saves in the {Path} record of {oph} a copy of the list {OLKS}, as the list of all links # that connect to {oph}. They all must end at {pini(oph)}. return path_hp_IMP.set_links(oph, OLKS) def get_links(oph): # Returns a list of all links stored in the {Path} record of {oph} # that end at {pini(oph)}. return path_hp_IMP.get_links(oph) def get_connecting_link(oph0, oph1): # Returns the link path that connects the end of oriented # path {oph0} to the start of the oriented path {oph1}, # if such a link has been stored in the respective {Path} # objects; or {None} if there is no such link. # # There must be at most one link path satisfyng those conditions. # That path must have been associated with both {oph0} and # {oph1} through {add_link}. return path_hp_IMP.get_connecting_link(oph0, oph1) # BLOCKS INSIDE CONTOUR PATHS # Each contour path {cr} (closed orented path that is part of the slice's # boundary) can be associated to a set of candidate filling blocks that # are contained in {cr} but not in any other contour path inside {cr}. These # links are associated to the underlying {Path} object of {cr} by # {assign_blocks_to_contours} below. The orientation of {cr} is ignored, # so that blocks are automatically shared with {path.rev(cr)}; but they # are not reserved by any operation that creates a new {Path} object, # such as {path.shift_contour} or {path.displace}. def assign_blocks_to_contours(OCRS, BCS): # The arguments are a list {OCRS} of contour paths (closed oriented # paths objects) and a list {BCS} of {Block} objects. The procedure # attaches to each contour path {ocr} in {OCRS} a list of the blocks of # {BCS} that are contained in {ocr} and in no other contour path that # is contained in {ocr}. # # The procedure assumes that the contour paths do not intersect and that # the moves of each block are all strctly inside or strictly outside # each contour path. The procedure fails if some block is not inside any # contour path. path_hp_IMP.assign_blocks_to_contours(OCRS, BCS) def get_blocks_in_contour(ocr): # Returns the list of blocks that were assined to contour path {ocr} # by {assign_blocks_to_contours}. return path_hp_IMP.get_blocks_in_contour(ocr) # PATH GROUPS # Each {Path} object can be assigned an integer {group} code. # This field is used, for instance, to indicate how filling elements # are to be joined into blocks for input to the toolpath contruction algorithms. def set_group(oph, igr): # Sets a mutable group index in the {Path} object underlying the oriente path {oph}. # Ignores the orientarion of {oph}. path_hp_IMP.set_group(oph, igr) def get_group(oph): # Returns the last group index assiged to the {Path} object underlying {oph} # by the last call of {set_group}; or {None} if there was no such call. return path_hp_IMP.get_group(oph) def separate_paths_by_group(OPHS): # Given a list {OPHS} of disjoint paths, rearranges them into a # a list {GRSS} of list of paths, where each element {GRSS[igr]} # is all elements with group index {igr}, as specified by # {path_hp.get_group}; or {None} if there is no # element with index {igr}. All these groups must be defined. # # The paths in each list in {GRSS} will be in the same order as they are in {OPHS}. # # Also returns the number of distinct non-empty groups found (which # may be less than {len(GRSS)}. # return path_hp_IMP.separate_paths_by_group(OPHS)