def __init__(self, shape=None): if shape is None: return self.shape = shape self.start, self.angle = self.shape.get_start_end_points(True, True) self.end = self.start self.geos = Geos([]) self.make_start_moves()
def make_own_cutter_compensation(self): toolwidth = self.shape.parentLayer.getToolRadius() self.geos = Geos([]) offtype = "in" if self.shape.cut_cor == 42 else "out" offshape = offShapeClass(parent=self.shape, offset=toolwidth, offtype=offtype) self.geos += offshape.rawoff
def getNewGeos(self, geos): # TODO use intersect class and update_start_end_points new_geos = Geos([]) for geo in geos.abs_iter(): if isinstance(geo, LineGeo): new_geos.extend(self.breakLineGeo(geo)) elif isinstance(geo, ArcGeo): new_geos.extend(self.breakArcGeo(geo)) else: new_geos.append(geo) return new_geos
def geos_preprocessing(self, parent): """ Do all the preprocessing required in order to have working offset algorithm. @param parent: The parent shape including the geometries to be offsetted. """ self.geos = Geos([]) for geo in parent.geos: if isinstance(geo, LineGeo): self.geos.append(OffLineGeo().abscopy(geo, parent)) elif isinstance(geo, ArcGeo): self.geos.append(OffArcGeo().abscopy(geo, parent)) else: logger.error("Should not be here") logger.debug(self.geos) self.make_shape_ccw() self.join_colinear_lines()
def breakArcGeo(self, arcGeo): """ Try to break passed arcGeo with any of the shapes on a break layers. Will break arcGeos recursively. @return: The list of geometries after breaking (arcGeo itself if no breaking happened) """ newGeos = Geos([]) for breakLayer in self.breakLayers: for breakShape in breakLayer.shapes.not_disabled_iter(): intersections = self.intersectArcGeometry(arcGeo, breakShape) if len(intersections) == 2: (near, far) = self.classifyIntersections(arcGeo, intersections) logger.debug("Arc %s broken from (%f, %f) to (%f, %f)" % (arcGeo.toShortString(), near.x, near.y, far.x, far.y)) newGeos.extend(self.breakArcGeo(ArcGeo(Ps=arcGeo.Ps, Pe=near, O=arcGeo.O, r=arcGeo.r, s_ang=arcGeo.s_ang, direction=arcGeo.ext))) newGeos.append(BreakGeo(near, far, breakShape.axis3_mill_depth, breakShape.f_g1_plane, breakShape.f_g1_depth)) newGeos.extend(self.breakArcGeo(ArcGeo(Ps=far, Pe=arcGeo.Pe, O=arcGeo.O, r=arcGeo.r, e_ang=arcGeo.e_ang, direction=arcGeo.ext))) return newGeos return [arcGeo]
def breakLineGeo(self, lineGeo): """ Try to break passed lineGeo with any of the shapes on a break layers. Will break lineGeos recursively. @return: The list of geometries after breaking (lineGeo itself if no breaking happened) """ newGeos = Geos([]) for breakLayer in self.breakLayers: for breakShape in breakLayer.shapes.not_disabled_iter(): intersections = self.intersectLineGeometry(lineGeo, breakShape) if len(intersections) == 2: (near, far) = self.classifyIntersections(lineGeo, intersections) logger.debug("Line %s broken from (%f, %f) to (%f, %f)" % (lineGeo.to_short_string(), near.x, near.y, far.x, far.y)) newGeos.extend(self.breakLineGeo(LineGeo(lineGeo.Ps, near))) newGeos.append(BreakGeo(near, far, breakShape.axis3_mill_depth, breakShape.f_g1_plane, breakShape.f_g1_depth)) newGeos.extend(self.breakLineGeo(LineGeo(far, lineGeo.Pe))) return newGeos return [lineGeo]
def make_own_cutter_compensation(self): toolwidth = self.shape.parentLayer.getToolRadius() geos = Geos([]) direction = -1 if self.shape.cut_cor == 41 else 1 if self.shape.closed: end, end_dir = self.shape.get_start_end_points(False, False) end_proj = Point(direction * end_dir.y, -direction * end_dir.x) prv_Pe = end + toolwidth * end_proj else: prv_Pe = None for geo_nr, geo in enumerate(self.shape.geos.abs_iter()): start, start_dir = geo.get_start_end_points(True, False) end, end_dir = geo.get_start_end_points(False, False) start_proj = Point(direction * start_dir.y, -direction * start_dir.x) end_proj = Point(direction * end_dir.y, -direction * end_dir.x) Ps = start + toolwidth * start_proj Pe = end + toolwidth * end_proj if Ps == Pe: continue if prv_Pe: r = geo.Ps.distance(Ps) d = (prv_Pe - geo.Ps).to3D().cross_product( (Ps - geo.Ps).to3D()).z if direction * d > 0 and prv_Pe != Ps: geos.append( ArcGeo(Ps=prv_Pe, Pe=Ps, O=geo.Ps, r=r, direction=d)) geos[-1].geo_nr = geo_nr # else: # geos.append(LineGeo(Ps=prv_Pe, Pe=Ps)) if isinstance(geo, LineGeo): geos.append(LineGeo(Ps, Pe)) geos[-1].geo_nr = geo_nr elif isinstance(geo, ArcGeo): O = geo.O r = O.distance(Ps) geos.append(ArcGeo(Ps=Ps, Pe=Pe, O=O, r=r, direction=geo.ext)) geos[-1].geo_nr = geo_nr # TODO other geos are not supported; disable them in gui for this option # else: # geos.append(geo) prv_Pe = Pe tot_length = 0 for geo in geos.abs_iter(): tot_length += geo.length reorder_shape = False for start_geo_nr in range(len(geos)): # if shape is not closed we may only remove shapes from the start last_geo_nr = start_geo_nr if self.shape.closed else 0 geos_adj = deepcopy(geos[start_geo_nr:]) + deepcopy( geos[:last_geo_nr]) new_geos = Geos([]) i = 0 while i in range(len(geos_adj)): geo = geos_adj[i] intersections = [] for j in range(i + 1, len(geos_adj)): intersection = Intersect.get_intersection_point( geos_adj[j], geos_adj[i]) if intersection and intersection != geos_adj[i].Ps: intersections.append([j, intersection]) if len(intersections) > 0: intersection = intersections[-1] change_end_of_geo = True if i == 0 and intersection[0] >= len(geos_adj) // 2: geo.update_start_end_points(True, intersection[1]) geos_adj[intersection[0]].update_start_end_points( False, intersection[1]) if len(intersections) > 1: intersection = intersections[-2] else: change_end_of_geo = False i += 1 if change_end_of_geo: geo.update_start_end_points(False, intersection[1]) i = intersection[0] geos_adj[i].update_start_end_points( True, intersection[1]) else: i += 1 # TODO # if len(new_geos) > 0 and not new_geos[-1].Pe.eq(geo.Ps, g.config.fitting_tolerance): # break # geo is disconnected new_geos.append(geo) if new_geos[0].Ps == new_geos[-1].Pe: break new_length = 0 for geo in new_geos: new_length += geo.length if tot_length * g.config.vars.Cutter_Compensation['min_length_considered']\ <= new_length <= tot_length * g.config.vars.Cutter_Compensation['max_length_considered'] and\ (not g.config.vars.Cutter_Compensation['direction_maintained'] or not self.shape.closed or self.shape.isDirectionOfGeosCCW(new_geos) != self.shape.cw): self.append(RapidPos(new_geos[0].Ps)) for geo in new_geos: if geo.Ps != geo.Pe: self.append(geo) reorder_shape = True break if reorder_shape and self.shape.closed: # we do not reorder the original shape if it's not closed self.shape.geos = Geos( self.shape.geos[geos[start_geo_nr].geo_nr:] + self.shape.geos[:geos[start_geo_nr].geo_nr]) if len(self.geos) == 0: self.append(RapidPos(self.start))
def make_start_moves(self): """ This function called to create the start move. It will be generated based on the given values for start and angle. """ self.geos = Geos([]) if g.config.machine_type == 'drag_knife': self.make_swivelknife_move() return # Get the start rad. and the length of the line segment at begin. start_rad = self.shape.parentLayer.start_radius # Get tool radius based on tool diameter. tool_rad = self.shape.parentLayer.getToolRadius() # Calculate the starting point with and without compensation. start = self.start angle = self.angle if self.shape.cut_cor == 40: self.append(RapidPos(start)) elif self.shape.cut_cor != 40 and not g.config.vars.Cutter_Compensation[ "done_by_machine"]: toolwidth = self.shape.parentLayer.getToolRadius() offtype = "in" if self.shape.cut_cor == 42 else "out" offshape = offShapeClass(parent=self.shape, offset=toolwidth, offtype=offtype) if len(offshape.rawoff) > 0: start, angle = offshape.rawoff[0].get_start_end_points( True, True) self.append(RapidPos(start)) self.geos += offshape.rawoff # Cutting Compensation Left elif self.shape.cut_cor == 41: # Center of the Starting Radius. Oein = start.get_arc_point(angle + pi / 2, start_rad + tool_rad) # Start Point of the Radius Ps_ein = Oein.get_arc_point(angle + pi, start_rad + tool_rad) # Start Point of the straight line segment at begin. Pg_ein = Ps_ein.get_arc_point(angle + pi / 2, start_rad) # Get the dive point for the starting contour and append it. start_ein = Pg_ein.get_arc_point(angle, tool_rad) self.append(RapidPos(start_ein)) # generate the Start Line and append it including the compensation. start_line = LineGeo(start_ein, Ps_ein) self.append(start_line) # generate the start rad. and append it. start_rad = ArcGeo(Ps=Ps_ein, Pe=start, O=Oein, r=start_rad + tool_rad, direction=1) self.append(start_rad) # Cutting Compensation Right elif self.shape.cut_cor == 42: # Center of the Starting Radius. Oein = start.get_arc_point(angle - pi / 2, start_rad + tool_rad) # Start Point of the Radius Ps_ein = Oein.get_arc_point(angle + pi, start_rad + tool_rad) # Start Point of the straight line segment at begin. Pg_ein = Ps_ein.get_arc_point(angle - pi / 2, start_rad) # Get the dive point for the starting contour and append it. start_ein = Pg_ein.get_arc_point(angle, tool_rad) self.append(RapidPos(start_ein)) # generate the Start Line and append it including the compensation. start_line = LineGeo(start_ein, Ps_ein) self.append(start_line) # generate the start rad. and append it. start_rad = ArcGeo(Ps=Ps_ein, Pe=start, O=Oein, r=start_rad + tool_rad, direction=0) self.append(start_rad)
class StMove(object): """ This Function generates the StartMove for each shape. It also performs the Plotting and Export of this moves. It is linked to the shape of its parent """ # only need default arguments here because of the change of usage with super in QGraphicsLineItem def __init__(self, shape=None): if shape is None: return self.shape = shape self.start, self.angle = self.shape.get_start_end_points(True, True) self.end = self.start self.geos = Geos([]) self.make_start_moves() def append(self, geo): # we don't want to additional scale / rotate the stmove geo # so no geo.make_abs_geo(self.shape.parentEntity) geo.make_abs_geo() self.geos.append(geo) def make_start_moves(self): """ This function called to create the start move. It will be generated based on the given values for start and angle. """ self.geos = Geos([]) if g.config.machine_type == 'drag_knife': self.make_swivelknife_move() return # Get the start rad. and the length of the line segment at begin. start_rad = self.shape.parentLayer.start_radius # Get tool radius based on tool diameter. tool_rad = self.shape.parentLayer.getToolRadius() # Calculate the starting point with and without compensation. start = self.start angle = self.angle if self.shape.cut_cor == 40: self.append(RapidPos(start)) elif self.shape.cut_cor != 40 and not g.config.vars.Cutter_Compensation[ "done_by_machine"]: toolwidth = self.shape.parentLayer.getToolRadius() offtype = "in" if self.shape.cut_cor == 42 else "out" offshape = offShapeClass(parent=self.shape, offset=toolwidth, offtype=offtype) if len(offshape.rawoff) > 0: start, angle = offshape.rawoff[0].get_start_end_points( True, True) self.append(RapidPos(start)) self.geos += offshape.rawoff # Cutting Compensation Left elif self.shape.cut_cor == 41: # Center of the Starting Radius. Oein = start.get_arc_point(angle + pi / 2, start_rad + tool_rad) # Start Point of the Radius Ps_ein = Oein.get_arc_point(angle + pi, start_rad + tool_rad) # Start Point of the straight line segment at begin. Pg_ein = Ps_ein.get_arc_point(angle + pi / 2, start_rad) # Get the dive point for the starting contour and append it. start_ein = Pg_ein.get_arc_point(angle, tool_rad) self.append(RapidPos(start_ein)) # generate the Start Line and append it including the compensation. start_line = LineGeo(start_ein, Ps_ein) self.append(start_line) # generate the start rad. and append it. start_rad = ArcGeo(Ps=Ps_ein, Pe=start, O=Oein, r=start_rad + tool_rad, direction=1) self.append(start_rad) # Cutting Compensation Right elif self.shape.cut_cor == 42: # Center of the Starting Radius. Oein = start.get_arc_point(angle - pi / 2, start_rad + tool_rad) # Start Point of the Radius Ps_ein = Oein.get_arc_point(angle + pi, start_rad + tool_rad) # Start Point of the straight line segment at begin. Pg_ein = Ps_ein.get_arc_point(angle - pi / 2, start_rad) # Get the dive point for the starting contour and append it. start_ein = Pg_ein.get_arc_point(angle, tool_rad) self.append(RapidPos(start_ein)) # generate the Start Line and append it including the compensation. start_line = LineGeo(start_ein, Ps_ein) self.append(start_line) # generate the start rad. and append it. start_rad = ArcGeo(Ps=Ps_ein, Pe=start, O=Oein, r=start_rad + tool_rad, direction=0) self.append(start_rad) def make_swivelknife_move(self): """ Set these variables for your tool and material @param offset: knife tip distance from tool centerline. The radius of the tool is used for this. """ offset = self.shape.parentLayer.getToolRadius() drag_angle = self.shape.drag_angle startnorm = offset * Point( 1, 0) # TODO make knife direction a config setting prvend, prvnorm = Point(), Point() first = True for geo in self.shape.geos.abs_iter(): if isinstance(geo, LineGeo): geo_b = deepcopy(geo) if first: first = False prvend = geo_b.Ps + startnorm prvnorm = startnorm norm = offset * (geo_b.Pe - geo_b.Ps).unit_vector() geo_b.Ps += norm geo_b.Pe += norm if not prvnorm == norm: direction = prvnorm.to3D().cross_product(norm.to3D()).z swivel = ArcGeo(Ps=prvend, Pe=geo_b.Ps, r=offset, direction=direction) swivel.drag = drag_angle < abs(swivel.ext) self.append(swivel) self.append(geo_b) prvend = geo_b.Pe prvnorm = norm elif isinstance(geo, ArcGeo): geo_b = deepcopy(geo) if first: first = False prvend = geo_b.Ps + startnorm prvnorm = startnorm if geo_b.ext > 0.0: norma = offset * Point(cos(geo_b.s_ang + pi / 2), sin(geo_b.s_ang + pi / 2)) norme = Point(cos(geo_b.e_ang + pi / 2), sin(geo_b.e_ang + pi / 2)) else: norma = offset * Point(cos(geo_b.s_ang - pi / 2), sin(geo_b.s_ang - pi / 2)) norme = Point(cos(geo_b.e_ang - pi / 2), sin(geo_b.e_ang - pi / 2)) geo_b.Ps += norma if norme.x > 0: geo_b.Pe = Point( geo_b.Pe.x + offset / (sqrt(1 + (norme.y / norme.x)**2)), geo_b.Pe.y + (offset * norme.y / norme.x) / (sqrt(1 + (norme.y / norme.x)**2))) elif norme.x == 0: geo_b.Pe = Point(geo_b.Pe.x, geo_b.Pe.y) else: geo_b.Pe = Point( geo_b.Pe.x - offset / (sqrt(1 + (norme.y / norme.x)**2)), geo_b.Pe.y - (offset * norme.y / norme.x) / (sqrt(1 + (norme.y / norme.x)**2))) if prvnorm != norma: direction = prvnorm.to3D().cross_product(norma.to3D()).z swivel = ArcGeo(Ps=prvend, Pe=geo_b.Ps, r=offset, direction=direction) swivel.drag = drag_angle < abs(swivel.ext) self.append(swivel) prvend = geo_b.Pe prvnorm = offset * norme if -pi < geo_b.ext < pi: self.append( ArcGeo(Ps=geo_b.Ps, Pe=geo_b.Pe, r=sqrt(geo_b.r**2 + offset**2), direction=geo_b.ext)) else: geo_b = ArcGeo(Ps=geo_b.Ps, Pe=geo_b.Pe, r=sqrt(geo_b.r**2 + offset**2), direction=-geo_b.ext) geo_b.ext = -geo_b.ext self.append(geo_b) # TODO support different geos, or disable them in the GUI # else: # self.append(copy(geo)) if not prvnorm == startnorm: direction = prvnorm.to3D().cross_product(startnorm.to3D()).z self.append( ArcGeo(Ps=prvend, Pe=prvend - prvnorm + startnorm, r=offset, direction=direction)) self.geos.insert(0, RapidPos(self.geos.abs_el(0).Ps)) self.geos[0].make_abs_geo() def make_path(self, drawHorLine, drawVerLine): for geo in self.geos.abs_iter(): drawVerLine(self.shape, geo.get_start_end_points(True)) geo.make_path(self.shape, drawHorLine) if len(self.geos): drawVerLine(self.shape, geo.get_start_end_points(False))
class offShapeClass(Shape): """ This Class is used to generate The fofset aof a shape according to: "A pair-wise offset Algorithm for 2D point sequence curve" http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.101.8855 """ def __init__(self, parent=Shape(), offset=1, offtype='in'): """ Standard method to initialize the class @param closed: Gives information about the shape, when it is closed this value becomes 1. Closed means it is a Polygon, otherwise it is a Polyline @param length: The total length of the shape including all geometries @param geos: The list with all geometries included in the shape. May also contain arcs. These will be reflected by multiple lines in order to easy calclations. """ super(offShapeClass, self).__init__(nr=parent.nr, closed=parent.closed, geos = []) self.offset = offset self.offtype = offtype self.segments = [] self.rawoff = [] self.geos_preprocessing(parent) self.make_segment_types() nextConvexPoint = [e for e in self.segments if isinstance(e, ConvexPoint)] # logger.debug(nextConvexPoint) # nextConvexPoint=[nextConvexPoint[31]] self.counter = 0 while len(nextConvexPoint): # [self.convex_vertex[-1]]: convex_vertex_nr = self.segments.index(nextConvexPoint[0]) # logger.debug(len(self.segments)) # logger.debug("convex_vertex: %s" % nextConvexPoint[0]) # logger.debug("convex_vertex_nr: %s" % convex_vertex_nr) forward, backward = self.PairWiseInterferenceDetection(convex_vertex_nr + 1, convex_vertex_nr - 1) # logger.debug("forward: %s, backward: %s" % (forward, backward)) if forward is None: return break if backward == 0 and forward == (len(self.segments) - 1) and self.closed: self.segments = [] break # Make Raw offset curve of forward and backward segment fw_rawoff_seg = self.make_rawoff_seg(self.segments[forward]) bw_rawoff_seg = self.make_rawoff_seg(self.segments[backward]) # Intersect the two segements iPoint = fw_rawoff_seg.find_inter_point(bw_rawoff_seg) if iPoint is None: logger.debug("fw_rawoff_seg: %s, bw_rawoff_seg: %s" %(fw_rawoff_seg,bw_rawoff_seg)) logger.debug("forward: %s, backward: %s, iPoint: %s =====================================" % (forward, backward, iPoint)) logger.debug(fw_rawoff_seg) logger.debug(bw_rawoff_seg) logger.error("No intersection found?!") self.segments = [] # raise Exception("No intersection found?!") break # Reomve the LIR from the PS Curce self.remove_LIR(forward, backward, iPoint) nextConvexPoint = [e for e in self.segments if isinstance(e, ConvexPoint)] # logger.debug(nextConvexPoint) # nextConvexPoint=[] # logger.debug(nextConvexPoint) for seg in self.segments: self.rawoff += [self.make_rawoff_seg(seg)] def __str__(self): """ Standard method to print the object @return: A string """ return "\nnr: %i" % self.nr +\ "\nclosed: %s" % self.closed +\ "\ngeos: %s" % self.geos +\ "\nofftype: %s" % self.offtype +\ "\noffset: %s" % self.offset +\ "\nsegments: %s" % self.segments +\ "\nrawoff %s" % self.rawoff def geos_preprocessing(self, parent): """ Do all the preprocessing required in order to have working offset algorithm. @param parent: The parent shape including the geometries to be offsetted. """ self.geos = Geos([]) for geo in parent.geos: if isinstance(geo, LineGeo): self.geos.append(OffLineGeo().abscopy(geo, parent)) elif isinstance(geo, ArcGeo): self.geos.append(OffArcGeo().abscopy(geo, parent)) else: logger.error("Should not be here") logger.debug(self.geos) self.make_shape_ccw() self.join_colinear_lines() def make_segment_types(self): """ This function is called in order to generate the segements according to Definiton 2. An edge (line) is a linear segment and a reflex vertex is is reflex segment. Colinear lines are assumed to be removed prior to the segment type definition. """ # Do only if more then 2 geometies # if len(self.geos) < 2: # return # Start with first Vertex if the line is closed if self.closed: start = 0 else: start = 1 geo1 = self.geos[0] if isinstance(geo1, LineGeo): geo1.start_normal = geo1.Ps.get_normal_vector(geo1.Pe) geo1.end_normal = geo1.Ps.get_normal_vector(geo1.Pe) else: geo1.start_normal = geo1.O.unit_vector(geo1.Ps, r = 1) geo1.end_normal = geo1.O.unit_vector(geo1.Pe, r = 1) if geo1.ext < 0: geo1.start_normal = geo1.start_normal * -1 geo1.end_normal = geo1.end_normal * -1 self.segments += [geo1] for i in range(start, len(self.geos)): geo1 = self.geos[i - 1] geo2 = self.geos[i] if i == start: if isinstance(geo1, LineGeo): geo1.start_normal = geo1.Ps.get_normal_vector(geo1.Pe) geo1.end_normal = geo1.Ps.get_normal_vector(geo1.Pe) else: geo1.start_normal = geo1.O.unit_vector(geo1.Ps, r = 1) geo1.end_normal = geo1.O.unit_vector(geo1.Pe, r = 1) if geo1.ext < 0: geo1.start_normal = geo1.start_normal * -1 geo1.end_normal = geo1.end_normal * -1 if isinstance(geo2, LineGeo): geo2.start_normal = geo2.Ps.get_normal_vector(geo2.Pe) geo2.end_normal = geo2.Ps.get_normal_vector(geo2.Pe) elif isinstance(geo2, ArcGeo): geo2.start_normal = geo2.O.unit_vector(geo2.Ps, r = 1) geo2.end_normal = geo2.O.unit_vector(geo2.Pe, r = 1) if geo2.ext < 0: geo2.start_normal = geo2.start_normal * -1 geo2.end_normal = geo2.end_normal * -1 # logger.debug("geo1: %s, geo2: %s" % (geo1, geo2)) # logger.debug("geo1.end_normal: %s, geo2.start_normal: %s" % (geo1.end_normal, geo2.start_normal)) # If it is a reflex vertex add a reflex segemnt (single point) # Add a Reflex Point if radius becomes below zero. # if isinstance(geo2, ArcGeo): # logger.debug(geo2) # geo2_off = self.make_rawoff_seg(geo2) # logger.debug(geo2_off) # if ((isinstance(geo2, ArcGeo)) and ((self.offtype == "out" and geo2.ext > 0) or (self.offtype == "in" and geo2.ext < 0)) and ((geo2.r - abs(self.offset)) <= 0.0)): newgeo2 = ConvexPoint(geo2.O.x, geo2.O.y) newgeo2.start_normal = geo2.start_normal newgeo2.end_normal = geo2.end_normal geo2 = newgeo2 # logger.debug(geo1.Pe.ccw(geo1.Pe + geo1.end_normal, # geo1.Pe + geo1.end_normal + # geo2.start_normal)) # logger.debug(geo1) # logger.debug(geo2) # logger.debug(geo1.end_normal) # logger.debug(geo2.start_normal) if (((geo1.Pe.ccw(geo1.Pe + geo1.end_normal, geo1.Pe + geo1.end_normal + geo2.start_normal) == 1) and self.offtype == "in") or (geo1.Pe.ccw(geo1.Pe + geo1.end_normal, geo1.Pe + geo1.end_normal + geo2.start_normal) == -1 and self.offtype == "out")): # logger.debug("reflex") geo1.Pe.start_normal = geo1.end_normal geo1.Pe.end_normal = geo2.start_normal self.segments += [geo1.Pe, geo2] elif (geo1.Pe.ccw(geo1.Pe + geo1.end_normal, geo1.Pe + geo1.end_normal + geo2.start_normal) == 0): self.segments += [geo2] # Add the linear segment which is a line connecting 2 vertices else: # logger.debug("convex") self.segments += [ConvexPoint(geo1.Pe.x, geo1.Pe.y), geo2] # logger.debug("Self.segments: %s" % self.segments) # self.segments_plot = deepcopy(self.segments) def make_rawoff_seg(self, seg): """ This function returns the rawoffset of a segement. A line for a line and a circle for a reflex segement. @param segment_nr: The nr of the segement for which the rawoffset segement shall be generated @ return: Returns the rawoffsetsegement of the defined segment """ # seg=self.segments[segment_nr] if self.offtype == "out": offset = -abs(self.offset) else: offset = abs(self.offset) # if segement 1 is inverted change End Point if isinstance(seg, OffLineGeo): Ps = seg.Ps + seg.start_normal * offset Pe = seg.Pe + seg.end_normal * offset return OffLineGeo(Ps, Pe) elif isinstance(seg, OffPoint): Ps = seg + seg.start_normal * offset Pe = seg + seg.end_normal * offset return OffArcGeo(Ps = Ps, Pe = Pe, O = deepcopy(seg), r = self.offset, direction = offset) elif isinstance(seg, OffArcGeo): Ps = seg.Ps + seg.start_normal * offset Pe = seg.Pe + seg.end_normal * offset if seg.ext > 0: return OffArcGeo(Ps = Ps, Pe = Pe, O = seg.O, r = seg.r + offset, direction = seg.ext) else: return OffArcGeo(Ps = Ps, Pe = Pe, O = seg.O, r = seg.r - offset, direction = seg.ext) elif isinstance(seg, ConvexPoint): Ps = seg + seg.start_normal * offset Pe = seg + seg.end_normal * offset return OffArcGeo(Ps = Ps, Pe = Pe, O = deepcopy(seg), r = self.offset, direction = offset) else: logger.error("Unsupportet Object type: %s" % type(seg)) def interfering_full(self, segment1, dir, segment2): """ Check if the Endpoint (dependent on dir) of segment 1 is interfering with segment 2 Definition according to Definition 6 @param segment 1: The first segment @param dir: The direction of the line 1, as given -1 reversed direction @param segment 2: The second segment to be checked @ return: Returns True or False """ # if segement 1 is inverted change End Point if isinstance(segment1, OffLineGeo) and dir == 1: Pe = segment1.Pe elif isinstance(segment1, OffLineGeo) and dir == -1: Pe = segment1.Ps elif isinstance(segment1, ConvexPoint): return False elif isinstance(segment1, OffPoint): Pe = segment1 elif isinstance(segment1, OffArcGeo) and dir == 1: Pe = segment1.Pe elif isinstance(segment1, OffArcGeo) and dir == -1: Pe = segment1.Ps else: logger.error("Unsupportet Object type: %s" % type(segment1)) # if we cut outside reverse the offset if self.offtype == "out": offset = -abs(self.offset) else: offset = abs(self.offset) if dir == 1: distance = segment2.distance(Pe + segment1.end_normal * offset) # self.interferingshapes += [OffLineGeo(Pe, Pe + segment1.end_normal * offset), # segment2, # OffArcGeo(O=Pe + segment1.end_normal * offset, # Ps=Pe, Pe=Pe , # s_ang=0, e_ang=2 * pi, r=self.offset)] else: # logger.debug(Pe) # logger.debug(segment1) # logger.debug(segment1.start_normal) distance = segment2.distance(Pe + segment1.start_normal * offset) # self.interferingshapes += [OffLineGeo(Pe, Pe + segment1.start_normal * offset), # segment2, # OffArcGeo(O=Pe + segment1.start_normal * offset, # Ps=Pe, Pe=Pe, # s_ang=0, e_ang=2 * pi, r=self.offset)] # logger.debug("Full distance: %s" % distance) # If the distance from the Segment to the Center of the Tangential Circle # is smaller then the radius we have an intersection return distance <= abs(offset) def interfering_partly(self, segment1, dir, segment2): """ Check if any tangential circle of segment 1 is interfering with segment 2. Definition according to Definition 5 @param segment 1: The first Line @param dir: The direction of the segment 1, as given -1 reversed direction @param segment 2: The second line to be checked @ return: Returns True or False """ if isinstance(segment1, ConvexPoint): logger.debug("Should not be here") return False else: offGeo = self.make_rawoff_seg(segment1) # self.interferingshapes += [offGeo] # if we cut outside reverse the offset if self.offtype == "out": offset = -abs(self.offset) else: offset = abs(self.offset) # offGeo=LineGeo(Ps,Pe) # logger.debug(segment2) # logger.debug(offGeo) # logger.debug("Partly distance: %s" % segment2.distance(offGeo)) # If the distance from the Line to the Center of the Tangential Circle # is smaller then the radius we have an intersection return segment2.distance(offGeo) <= abs(offset) def Interfering_relation(self, segment1, segment2): """ Check the interfering relation between two segements (segment1 and segment2). Definition acccording to Definition 6 @param segment1: The first segment (forward) @param segment2: The second segment (backward) @return: Returns one of [full, partial, reverse, None] interfering relations for both segments """ # logger.debug("\nChecking: segment1: %s, \nsegment2: %s" % (segment1, segment2)) # Check if segments are equal if segment1 == segment2: return None, None if self.interfering_full(segment1, 1, segment2): self.interfering_partly(segment1, 1, segment2) L1_status = "full" elif self.interfering_partly(segment1, 1, segment2): L1_status = "partial" else: L1_status = "reverse" if self.interfering_full(segment2, -1, segment1): self.interfering_partly(segment2, -1, segment1) L2_status = "full" elif self.interfering_partly(segment2, -1, segment1): L2_status = "partial" else: L2_status = "reverse" # logger.debug("Start Status: L1_status: %s,L2_status: %s" % (L1_status, L2_status)) return [L1_status, L2_status] def PairWiseInterferenceDetection(self, forward, backward,): """ Returns the first forward and backward segment nr. for which both interfering conditions are partly. @param foward: The nr of the first forward segment @param backward: the nr. of the first backward segment @return: forward, backward """ val = 2000 # self.counter = 0 L1_status, L2_status = "full", "full" # Repeat until we reached the Partial-interfering-relation while not(L1_status == "partial" and L2_status == "partial"): self.interferingshapes = [] self.counter += 1 if forward >= len(self.segments): forward = 0 segment1 = self.segments[forward] segment2 = self.segments[backward] if isinstance(segment1, ConvexPoint): forward += 1 if forward >= len(self.segments): forward = 0 segment1 = self.segments[forward] # logger.debug("Forward ConvexPoint") if isinstance(segment2, ConvexPoint): backward -= 1 segment2 = self.segments[backward] # logger.debug("Backward ConvexPoint") # logger.debug("Checking: forward: %s, backward: %s" % (forward, backward)) [L1_status, L2_status] = self.Interfering_relation(segment1, segment2) # logger.debug("Start Status: L1_status: %s,L2_status: %s" % (L1_status, L2_status)) """ The reverse interfering segment is replaced by the first non-reverse-interfering segment along it's tracking direction """ if L1_status == "reverse": while L1_status == "reverse": self.counter += 1 # logger.debug(self.counter) if self.counter > val: break if self.counter >= val: self.interferingshapes = [] forward += 1 if forward >= len(self.segments): forward = 0 segment1 = self.segments[forward] if isinstance(segment1, ConvexPoint): forward += 1 segment1 = self.segments[forward] # logger.debug("Forward ConvexPoint") # logger.debug("Reverse Replace Checking: forward: %s, backward: %s" %(forward, backward)) [L1_status, L2_status] = self.Interfering_relation(segment1, segment2) # logger.debug("Checking: forward: %s, backward: %s" %(forward, backward)) # logger.debug("Replace Reverse: L1_status: %s,L2_status: %s" %(L1_status,L2_status)) elif L2_status == "reverse": while L2_status == "reverse": self.counter += 1 # logger.debug(self.counter) if self.counter > val: break if self.counter >= val: self.interferingshapes = [] backward -= 1 # logger.debug("Reveerse Replace Checking: forward: %s, backward: %s" %(forward, backward)) segment2 = self.segments[backward] if isinstance(segment2, ConvexPoint): backward -= 1 segment2 = self.segments[backward] # logger.debug("Backward ConvexPoint") [L1_status, L2_status] = self.Interfering_relation(segment1, segment2) # logger.debug("Checking: forward: %s, backward: %s" %(forward, backward)) # logger.debug("Replace Reverse: L1_status: %s,L2_status: %s" %(L1_status,L2_status)) """ Full interfering segment is replaced by the nexst segemnt along the tracking direction. """ if L1_status == "full" and (L2_status == "partial" or L2_status == "full"): forward += 1 elif L2_status == "full" and (L1_status == "partial" or L1_status == "partial"): backward -= 1 # If The begin end point is the end end point we are done. if L1_status is None and L2_status is None: # logger.debug("Begin = End; Remove all") return len(self.segments) - 1, 0 # logger.debug(self.counter) # logger.debug("L1_status: %s,L2_status: %s" %(L1_status,L2_status)) if self.counter == val: self.interferingshapes = [] if self.counter > val: # 26: logger.error("No partial - partial status found") return None, None # logger.debug("Result: forward: %s, backward: %s" %(forward, backward)) return forward, backward def remove_LIR(self, forward, backward, iPoint): """ The instance is used to remove the LIR from the PS curve. @param forward: The forward segment of the LIR @param backward: The backward segement of the LIR @param iPoint: The Intersection point of the LIR """ if backward > forward: pop_range = self.segments[backward + 1:len(self.segments)] pop_range += self.segments[0:forward] elif backward<0: pop_range = self.segments[len(self.segments)+backward + 1:len(self.segments)] pop_range += self.segments[0:forward] else: pop_range = self.segments[backward + 1:forward] if self.offtype == "out": rev = True else: rev = False # Modify the first segment and the last segment of the LIR self.segments[forward] = self.segments[forward].trim(Point=iPoint, dir=1, rev_norm=rev) self.segments[backward] = self.segments[backward].trim(Point=iPoint, dir=-1, rev_norm=rev) # Remove the segments which are inbetween the LIR self.segments = [x for x in self.segments if x not in pop_range]
def make_own_cutter_compensation(self): toolwidth = self.shape.parentLayer.getToolRadius() geos = Geos([]) direction = -1 if self.shape.cut_cor == 41 else 1 if self.shape.closed: end, end_dir = self.shape.get_start_end_points(False, False) end_proj = Point(direction * end_dir.y, -direction * end_dir.x) prv_Pe = end + toolwidth * end_proj else: prv_Pe = None for geo_nr, geo in enumerate(self.shape.geos.abs_iter()): start, start_dir = geo.get_start_end_points(True, False) end, end_dir = geo.get_start_end_points(False, False) start_proj = Point(direction * start_dir.y, -direction * start_dir.x) end_proj = Point(direction * end_dir.y, -direction * end_dir.x) Ps = start + toolwidth * start_proj Pe = end + toolwidth * end_proj if Ps == Pe: continue if prv_Pe: r = geo.Ps.distance(Ps) d = (prv_Pe - geo.Ps).to3D().cross_product((Ps - geo.Ps).to3D()).z if direction * d > 0 and prv_Pe != Ps: geos.append(ArcGeo(Ps=prv_Pe, Pe=Ps, O=geo.Ps, r=r, direction=d)) geos[-1].geo_nr = geo_nr # else: # geos.append(LineGeo(Ps=prv_Pe, Pe=Ps)) if isinstance(geo, LineGeo): geos.append(LineGeo(Ps, Pe)) geos[-1].geo_nr = geo_nr elif isinstance(geo, ArcGeo): O = geo.O r = O.distance(Ps) geos.append(ArcGeo(Ps=Ps, Pe=Pe, O=O, r=r, direction=geo.ext)) geos[-1].geo_nr = geo_nr # TODO other geos are not supported; disable them in gui for this option # else: # geos.append(geo) prv_Pe = Pe tot_length = 0 for geo in geos.abs_iter(): tot_length += geo.length reorder_shape = False for start_geo_nr in range(len(geos)): # if shape is not closed we may only remove shapes from the start last_geo_nr = start_geo_nr if self.shape.closed else 0 geos_adj = deepcopy(geos[start_geo_nr:]) + deepcopy(geos[:last_geo_nr]) new_geos = Geos([]) i = 0 while i in range(len(geos_adj)): geo = geos_adj[i] intersections = [] for j in range(i+1, len(geos_adj)): intersection = Intersect.get_intersection_point(geos_adj[j], geos_adj[i]) if intersection and intersection != geos_adj[i].Ps: intersections.append([j, intersection]) if len(intersections) > 0: intersection = intersections[-1] change_end_of_geo = True if i == 0 and intersection[0] >= len(geos_adj)//2: geo.update_start_end_points(True, intersection[1]) geos_adj[intersection[0]].update_start_end_points(False, intersection[1]) if len(intersections) > 1: intersection = intersections[-2] else: change_end_of_geo = False i += 1 if change_end_of_geo: geo.update_start_end_points(False, intersection[1]) i = intersection[0] geos_adj[i].update_start_end_points(True, intersection[1]) else: i += 1 # TODO # if len(new_geos) > 0 and not new_geos[-1].Pe.eq(geo.Ps, g.config.fitting_tolerance): # break # geo is disconnected new_geos.append(geo) if new_geos[0].Ps == new_geos[-1].Pe: break new_length = 0 for geo in new_geos: new_length += geo.length if tot_length * g.config.vars.Cutter_Compensation['min_length_considered']\ <= new_length <= tot_length * g.config.vars.Cutter_Compensation['max_length_considered'] and\ (not g.config.vars.Cutter_Compensation['direction_maintained'] or not self.shape.closed or self.shape.isDirectionOfGeosCCW(new_geos) != self.shape.cw): self.append(RapidPos(new_geos[0].Ps)) for geo in new_geos: if geo.Ps != geo.Pe: self.append(geo) reorder_shape = True break if reorder_shape and self.shape.closed: # we do not reorder the original shape if it's not closed self.shape.geos = Geos(self.shape.geos[geos[start_geo_nr].geo_nr:] + self.shape.geos[:geos[start_geo_nr].geo_nr]) if len(self.geos) == 0: self.append(RapidPos(self.start))
class StMove(object): """ This Function generates the StartMove for each shape. It also performs the Plotting and Export of this moves. It is linked to the shape of its parent """ # only need default arguments here because of the change of usage with super in QGraphicsLineItem def __init__(self, shape=None): if shape is None: return self.shape = shape self.start, self.angle = self.shape.get_start_end_points(True, True) self.end = self.start self.geos = Geos([]) self.make_start_moves() def append(self, geo): # we don't want to additional scale / rotate the stmove geo # so no geo.make_abs_geo(self.shape.parentEntity) geo.make_abs_geo() self.geos.append(geo) def make_start_moves(self): """ This function called to create the start move. It will be generated based on the given values for start and angle. """ self.geos = Geos([]) if g.config.machine_type == 'drag_knife': self.make_swivelknife_move() return elif self.shape.cut_cor != 40 and not g.config.vars.Cutter_Compensation["done_by_machine"]: self.make_own_cutter_compensation() return # Get the start rad. and the length of the line segment at begin. start_rad = self.shape.parentLayer.start_radius # Get tool radius based on tool diameter. tool_rad = self.shape.parentLayer.getToolRadius() # Calculate the starting point with and without compensation. start = self.start angle = self.angle if self.shape.cut_cor == 40: self.append(RapidPos(start)) # Cutting Compensation Left elif self.shape.cut_cor == 41: # Center of the Starting Radius. Oein = start.get_arc_point(angle + pi/2, start_rad + tool_rad) # Start Point of the Radius Pa_ein = Oein.get_arc_point(angle + pi, start_rad + tool_rad) # Start Point of the straight line segment at begin. Pg_ein = Pa_ein.get_arc_point(angle + pi/2, start_rad) # Get the dive point for the starting contour and append it. start_ein = Pg_ein.get_arc_point(angle, tool_rad) self.append(RapidPos(start_ein)) # generate the Start Line and append it including the compensation. start_line = LineGeo(start_ein, Pa_ein) self.append(start_line) # generate the start rad. and append it. start_rad = ArcGeo(Ps=Pa_ein, Pe=start, O=Oein, r=start_rad + tool_rad, direction=1) self.append(start_rad) # Cutting Compensation Right elif self.shape.cut_cor == 42: # Center of the Starting Radius. Oein = start.get_arc_point(angle - pi/2, start_rad + tool_rad) # Start Point of the Radius Pa_ein = Oein.get_arc_point(angle + pi, start_rad + tool_rad) # Start Point of the straight line segment at begin. Pg_ein = Pa_ein.get_arc_point(angle - pi/2, start_rad) # Get the dive point for the starting contour and append it. start_ein = Pg_ein.get_arc_point(angle, tool_rad) self.append(RapidPos(start_ein)) # generate the Start Line and append it including the compensation. start_line = LineGeo(start_ein, Pa_ein) self.append(start_line) # generate the start rad. and append it. start_rad = ArcGeo(Ps=Pa_ein, Pe=start, O=Oein, r=start_rad + tool_rad, direction=0) self.append(start_rad) def make_swivelknife_move(self): """ Set these variables for your tool and material @param offset: knife tip distance from tool centerline. The radius of the tool is used for this. """ offset = self.shape.parentLayer.getToolRadius() drag_angle = self.shape.drag_angle startnorm = offset*Point(1, 0) # TODO make knife direction a config setting prvend, prvnorm = Point(), Point() first = True for geo in self.shape.geos.abs_iter(): if isinstance(geo, LineGeo): geo_b = deepcopy(geo) if first: first = False prvend = geo_b.Ps + startnorm prvnorm = startnorm norm = offset * (geo_b.Pe - geo_b.Ps).unit_vector() geo_b.Ps += norm geo_b.Pe += norm if not prvnorm == norm: direction = prvnorm.to3D().cross_product(norm.to3D()).z swivel = ArcGeo(Ps=prvend, Pe=geo_b.Ps, r=offset, direction=direction) swivel.drag = drag_angle < abs(swivel.ext) self.append(swivel) self.append(geo_b) prvend = geo_b.Pe prvnorm = norm elif isinstance(geo, ArcGeo): geo_b = deepcopy(geo) if first: first = False prvend = geo_b.Ps + startnorm prvnorm = startnorm if geo_b.ext > 0.0: norma = offset*Point(cos(geo_b.s_ang+pi/2), sin(geo_b.s_ang+pi/2)) norme = Point(cos(geo_b.e_ang+pi/2), sin(geo_b.e_ang+pi/2)) else: norma = offset*Point(cos(geo_b.s_ang-pi/2), sin(geo_b.s_ang-pi/2)) norme = Point(cos(geo_b.e_ang-pi/2), sin(geo_b.e_ang-pi/2)) geo_b.Ps += norma if norme.x > 0: geo_b.Pe = Point(geo_b.Pe.x+offset/(sqrt(1+(norme.y/norme.x)**2)), geo_b.Pe.y+(offset*norme.y/norme.x)/(sqrt(1+(norme.y/norme.x)**2))) elif norme.x == 0: geo_b.Pe = Point(geo_b.Pe.x, geo_b.Pe.y) else: geo_b.Pe = Point(geo_b.Pe.x-offset/(sqrt(1+(norme.y/norme.x)**2)), geo_b.Pe.y-(offset*norme.y/norme.x)/(sqrt(1+(norme.y/norme.x)**2))) if prvnorm != norma: direction = prvnorm.to3D().cross_product(norma.to3D()).z swivel = ArcGeo(Ps=prvend, Pe=geo_b.Ps, r=offset, direction=direction) swivel.drag = drag_angle < abs(swivel.ext) self.append(swivel) prvend = geo_b.Pe prvnorm = offset*norme if -pi < geo_b.ext < pi: self.append(ArcGeo(Ps=geo_b.Ps, Pe=geo_b.Pe, r=sqrt(geo_b.r**2+offset**2), direction=geo_b.ext)) else: geo_b = ArcGeo(Ps=geo_b.Ps, Pe=geo_b.Pe, r=sqrt(geo_b.r**2+offset**2), direction=-geo_b.ext) geo_b.ext = -geo_b.ext self.append(geo_b) # TODO support different geos, or disable them in the GUI # else: # self.append(copy(geo)) if not prvnorm == startnorm: direction = prvnorm.to3D().cross_product(startnorm.to3D()).z self.append(ArcGeo(Ps=prvend, Pe=prvend-prvnorm+startnorm, r=offset, direction=direction)) self.geos.insert(0, RapidPos(self.geos.abs_el(0).Ps)) self.geos[0].make_abs_geo() def make_own_cutter_compensation(self): toolwidth = self.shape.parentLayer.getToolRadius() geos = Geos([]) direction = -1 if self.shape.cut_cor == 41 else 1 if self.shape.closed: end, end_dir = self.shape.get_start_end_points(False, False) end_proj = Point(direction * end_dir.y, -direction * end_dir.x) prv_Pe = end + toolwidth * end_proj else: prv_Pe = None for geo_nr, geo in enumerate(self.shape.geos.abs_iter()): start, start_dir = geo.get_start_end_points(True, False) end, end_dir = geo.get_start_end_points(False, False) start_proj = Point(direction * start_dir.y, -direction * start_dir.x) end_proj = Point(direction * end_dir.y, -direction * end_dir.x) Ps = start + toolwidth * start_proj Pe = end + toolwidth * end_proj if Ps == Pe: continue if prv_Pe: r = geo.Ps.distance(Ps) d = (prv_Pe - geo.Ps).to3D().cross_product((Ps - geo.Ps).to3D()).z if direction * d > 0 and prv_Pe != Ps: geos.append(ArcGeo(Ps=prv_Pe, Pe=Ps, O=geo.Ps, r=r, direction=d)) geos[-1].geo_nr = geo_nr # else: # geos.append(LineGeo(Ps=prv_Pe, Pe=Ps)) if isinstance(geo, LineGeo): geos.append(LineGeo(Ps, Pe)) geos[-1].geo_nr = geo_nr elif isinstance(geo, ArcGeo): O = geo.O r = O.distance(Ps) geos.append(ArcGeo(Ps=Ps, Pe=Pe, O=O, r=r, direction=geo.ext)) geos[-1].geo_nr = geo_nr # TODO other geos are not supported; disable them in gui for this option # else: # geos.append(geo) prv_Pe = Pe tot_length = 0 for geo in geos.abs_iter(): tot_length += geo.length reorder_shape = False for start_geo_nr in range(len(geos)): # if shape is not closed we may only remove shapes from the start last_geo_nr = start_geo_nr if self.shape.closed else 0 geos_adj = deepcopy(geos[start_geo_nr:]) + deepcopy(geos[:last_geo_nr]) new_geos = Geos([]) i = 0 while i in range(len(geos_adj)): geo = geos_adj[i] intersections = [] for j in range(i+1, len(geos_adj)): intersection = Intersect.get_intersection_point(geos_adj[j], geos_adj[i]) if intersection and intersection != geos_adj[i].Ps: intersections.append([j, intersection]) if len(intersections) > 0: intersection = intersections[-1] change_end_of_geo = True if i == 0 and intersection[0] >= len(geos_adj)//2: geo.update_start_end_points(True, intersection[1]) geos_adj[intersection[0]].update_start_end_points(False, intersection[1]) if len(intersections) > 1: intersection = intersections[-2] else: change_end_of_geo = False i += 1 if change_end_of_geo: geo.update_start_end_points(False, intersection[1]) i = intersection[0] geos_adj[i].update_start_end_points(True, intersection[1]) else: i += 1 # TODO # if len(new_geos) > 0 and not new_geos[-1].Pe.eq(geo.Ps, g.config.fitting_tolerance): # break # geo is disconnected new_geos.append(geo) if new_geos[0].Ps == new_geos[-1].Pe: break new_length = 0 for geo in new_geos: new_length += geo.length if tot_length * g.config.vars.Cutter_Compensation['min_length_considered']\ <= new_length <= tot_length * g.config.vars.Cutter_Compensation['max_length_considered'] and\ (not g.config.vars.Cutter_Compensation['direction_maintained'] or not self.shape.closed or self.shape.isDirectionOfGeosCCW(new_geos) != self.shape.cw): self.append(RapidPos(new_geos[0].Ps)) for geo in new_geos: if geo.Ps != geo.Pe: self.append(geo) reorder_shape = True break if reorder_shape and self.shape.closed: # we do not reorder the original shape if it's not closed self.shape.geos = Geos(self.shape.geos[geos[start_geo_nr].geo_nr:] + self.shape.geos[:geos[start_geo_nr].geo_nr]) if len(self.geos) == 0: self.append(RapidPos(self.start)) def make_path(self, drawHorLine, drawVerLine): for geo in self.geos.abs_iter(): drawVerLine(self.shape, geo.get_start_end_points(True)) geo.make_path(self.shape, drawHorLine) drawVerLine(self.shape, geo.get_start_end_points(False))
class StMove(object): """ This Function generates the StartMove for each shape. It also performs the Plotting and Export of this moves. It is linked to the shape of its parent """ # only need default arguments here because of the change of usage with super in QGraphicsLineItem def __init__(self, shape=None): if shape is None: return self.shape = shape self.start, self.angle = self.shape.get_start_end_points(True, True) self.end = self.start self.geos = Geos([]) self.make_start_moves() def append(self, geo): # we don't want to additional scale / rotate the stmove geo # so no geo.make_abs_geo(self.shape.parentEntity) geo.make_abs_geo() self.geos.append(geo) def make_start_moves(self): """ This function called to create the start move. It will be generated based on the given values for start and angle. """ self.geos = Geos([]) if g.config.machine_type == 'drag_knife': self.make_swivelknife_move() return elif self.shape.cut_cor != 40 and not g.config.vars.Cutter_Compensation[ "done_by_machine"]: self.make_own_cutter_compensation() return # Get the start rad. and the length of the line segment at begin. start_rad = self.shape.parentLayer.start_radius # Get tool radius based on tool diameter. tool_rad = self.shape.parentLayer.getToolRadius() # Calculate the starting point with and without compensation. start = self.start angle = self.angle if self.shape.cut_cor == 40: self.append(RapidPos(start)) # Cutting Compensation Left elif self.shape.cut_cor == 41: # Center of the Starting Radius. Oein = start.get_arc_point(angle + pi / 2, start_rad + tool_rad) # Start Point of the Radius Pa_ein = Oein.get_arc_point(angle + pi, start_rad + tool_rad) # Start Point of the straight line segment at begin. Pg_ein = Pa_ein.get_arc_point(angle + pi / 2, start_rad) # Get the dive point for the starting contour and append it. start_ein = Pg_ein.get_arc_point(angle, tool_rad) self.append(RapidPos(start_ein)) # generate the Start Line and append it including the compensation. start_line = LineGeo(start_ein, Pa_ein) self.append(start_line) # generate the start rad. and append it. start_rad = ArcGeo(Ps=Pa_ein, Pe=start, O=Oein, r=start_rad + tool_rad, direction=1) self.append(start_rad) # Cutting Compensation Right elif self.shape.cut_cor == 42: # Center of the Starting Radius. Oein = start.get_arc_point(angle - pi / 2, start_rad + tool_rad) # Start Point of the Radius Pa_ein = Oein.get_arc_point(angle + pi, start_rad + tool_rad) # Start Point of the straight line segment at begin. Pg_ein = Pa_ein.get_arc_point(angle - pi / 2, start_rad) # Get the dive point for the starting contour and append it. start_ein = Pg_ein.get_arc_point(angle, tool_rad) self.append(RapidPos(start_ein)) # generate the Start Line and append it including the compensation. start_line = LineGeo(start_ein, Pa_ein) self.append(start_line) # generate the start rad. and append it. start_rad = ArcGeo(Ps=Pa_ein, Pe=start, O=Oein, r=start_rad + tool_rad, direction=0) self.append(start_rad) def make_swivelknife_move(self): """ Set these variables for your tool and material @param offset: knife tip distance from tool centerline. The radius of the tool is used for this. """ offset = self.shape.parentLayer.getToolRadius() drag_angle = self.shape.drag_angle startnorm = offset * Point( 1, 0) # TODO make knife direction a config setting prvend, prvnorm = Point(), Point() first = True for geo in self.shape.geos.abs_iter(): if isinstance(geo, LineGeo): geo_b = deepcopy(geo) if first: first = False prvend = geo_b.Ps + startnorm prvnorm = startnorm norm = offset * (geo_b.Pe - geo_b.Ps).unit_vector() geo_b.Ps += norm geo_b.Pe += norm if not prvnorm == norm: direction = prvnorm.to3D().cross_product(norm.to3D()).z swivel = ArcGeo(Ps=prvend, Pe=geo_b.Ps, r=offset, direction=direction) swivel.drag = drag_angle < abs(swivel.ext) self.append(swivel) self.append(geo_b) prvend = geo_b.Pe prvnorm = norm elif isinstance(geo, ArcGeo): geo_b = deepcopy(geo) if first: first = False prvend = geo_b.Ps + startnorm prvnorm = startnorm if geo_b.ext > 0.0: norma = offset * Point(cos(geo_b.s_ang + pi / 2), sin(geo_b.s_ang + pi / 2)) norme = Point(cos(geo_b.e_ang + pi / 2), sin(geo_b.e_ang + pi / 2)) else: norma = offset * Point(cos(geo_b.s_ang - pi / 2), sin(geo_b.s_ang - pi / 2)) norme = Point(cos(geo_b.e_ang - pi / 2), sin(geo_b.e_ang - pi / 2)) geo_b.Ps += norma if norme.x > 0: geo_b.Pe = Point( geo_b.Pe.x + offset / (sqrt(1 + (norme.y / norme.x)**2)), geo_b.Pe.y + (offset * norme.y / norme.x) / (sqrt(1 + (norme.y / norme.x)**2))) elif norme.x == 0: geo_b.Pe = Point(geo_b.Pe.x, geo_b.Pe.y) else: geo_b.Pe = Point( geo_b.Pe.x - offset / (sqrt(1 + (norme.y / norme.x)**2)), geo_b.Pe.y - (offset * norme.y / norme.x) / (sqrt(1 + (norme.y / norme.x)**2))) if prvnorm != norma: direction = prvnorm.to3D().cross_product(norma.to3D()).z swivel = ArcGeo(Ps=prvend, Pe=geo_b.Ps, r=offset, direction=direction) swivel.drag = drag_angle < abs(swivel.ext) self.append(swivel) prvend = geo_b.Pe prvnorm = offset * norme if -pi < geo_b.ext < pi: self.append( ArcGeo(Ps=geo_b.Ps, Pe=geo_b.Pe, r=sqrt(geo_b.r**2 + offset**2), direction=geo_b.ext)) else: geo_b = ArcGeo(Ps=geo_b.Ps, Pe=geo_b.Pe, r=sqrt(geo_b.r**2 + offset**2), direction=-geo_b.ext) geo_b.ext = -geo_b.ext self.append(geo_b) # TODO support different geos, or disable them in the GUI # else: # self.append(copy(geo)) if not prvnorm == startnorm: direction = prvnorm.to3D().cross_product(startnorm.to3D()).z self.append( ArcGeo(Ps=prvend, Pe=prvend - prvnorm + startnorm, r=offset, direction=direction)) self.geos.insert(0, RapidPos(self.geos.abs_el(0).Ps)) self.geos[0].make_abs_geo() def make_own_cutter_compensation(self): toolwidth = self.shape.parentLayer.getToolRadius() geos = Geos([]) direction = -1 if self.shape.cut_cor == 41 else 1 if self.shape.closed: end, end_dir = self.shape.get_start_end_points(False, False) end_proj = Point(direction * end_dir.y, -direction * end_dir.x) prv_Pe = end + toolwidth * end_proj else: prv_Pe = None for geo_nr, geo in enumerate(self.shape.geos.abs_iter()): start, start_dir = geo.get_start_end_points(True, False) end, end_dir = geo.get_start_end_points(False, False) start_proj = Point(direction * start_dir.y, -direction * start_dir.x) end_proj = Point(direction * end_dir.y, -direction * end_dir.x) Ps = start + toolwidth * start_proj Pe = end + toolwidth * end_proj if Ps == Pe: continue if prv_Pe: r = geo.Ps.distance(Ps) d = (prv_Pe - geo.Ps).to3D().cross_product( (Ps - geo.Ps).to3D()).z if direction * d > 0 and prv_Pe != Ps: geos.append( ArcGeo(Ps=prv_Pe, Pe=Ps, O=geo.Ps, r=r, direction=d)) geos[-1].geo_nr = geo_nr # else: # geos.append(LineGeo(Ps=prv_Pe, Pe=Ps)) if isinstance(geo, LineGeo): geos.append(LineGeo(Ps, Pe)) geos[-1].geo_nr = geo_nr elif isinstance(geo, ArcGeo): O = geo.O r = O.distance(Ps) geos.append(ArcGeo(Ps=Ps, Pe=Pe, O=O, r=r, direction=geo.ext)) geos[-1].geo_nr = geo_nr # TODO other geos are not supported; disable them in gui for this option # else: # geos.append(geo) prv_Pe = Pe tot_length = 0 for geo in geos.abs_iter(): tot_length += geo.length reorder_shape = False for start_geo_nr in range(len(geos)): # if shape is not closed we may only remove shapes from the start last_geo_nr = start_geo_nr if self.shape.closed else 0 geos_adj = deepcopy(geos[start_geo_nr:]) + deepcopy( geos[:last_geo_nr]) new_geos = Geos([]) i = 0 while i in range(len(geos_adj)): geo = geos_adj[i] intersections = [] for j in range(i + 1, len(geos_adj)): intersection = Intersect.get_intersection_point( geos_adj[j], geos_adj[i]) if intersection and intersection != geos_adj[i].Ps: intersections.append([j, intersection]) if len(intersections) > 0: intersection = intersections[-1] change_end_of_geo = True if i == 0 and intersection[0] >= len(geos_adj) // 2: geo.update_start_end_points(True, intersection[1]) geos_adj[intersection[0]].update_start_end_points( False, intersection[1]) if len(intersections) > 1: intersection = intersections[-2] else: change_end_of_geo = False i += 1 if change_end_of_geo: geo.update_start_end_points(False, intersection[1]) i = intersection[0] geos_adj[i].update_start_end_points( True, intersection[1]) else: i += 1 # TODO # if len(new_geos) > 0 and not new_geos[-1].Pe.eq(geo.Ps, g.config.fitting_tolerance): # break # geo is disconnected new_geos.append(geo) if new_geos[0].Ps == new_geos[-1].Pe: break new_length = 0 for geo in new_geos: new_length += geo.length if tot_length * g.config.vars.Cutter_Compensation['min_length_considered']\ <= new_length <= tot_length * g.config.vars.Cutter_Compensation['max_length_considered'] and\ (not g.config.vars.Cutter_Compensation['direction_maintained'] or not self.shape.closed or self.shape.isDirectionOfGeosCCW(new_geos) != self.shape.cw): self.append(RapidPos(new_geos[0].Ps)) for geo in new_geos: if geo.Ps != geo.Pe: self.append(geo) reorder_shape = True break if reorder_shape and self.shape.closed: # we do not reorder the original shape if it's not closed self.shape.geos = Geos( self.shape.geos[geos[start_geo_nr].geo_nr:] + self.shape.geos[:geos[start_geo_nr].geo_nr]) if len(self.geos) == 0: self.append(RapidPos(self.start)) def make_path(self, drawHorLine, drawVerLine): for geo in self.geos.abs_iter(): drawVerLine(self.shape, geo.get_start_end_points(True)) geo.make_path(self.shape, drawHorLine) drawVerLine(self.shape, geo.get_start_end_points(False))
class offShapeClass(Shape): """ This Class is used to generate The fofset aof a shape according to: "A pair-wise offset Algorithm for 2D point sequence curve" http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.101.8855 """ def __init__(self, parent=Shape(), offset=1, offtype='in'): """ Standard method to initialize the class @param closed: Gives information about the shape, when it is closed this value becomes 1. Closed means it is a Polygon, otherwise it is a Polyline @param length: The total length of the shape including all geometries @param geos: The list with all geometries included in the shape. May also contain arcs. These will be reflected by multiple lines in order to easy calclations. """ super(offShapeClass, self).__init__(nr=parent.nr, closed=parent.closed, geos=[]) self.offset = offset self.offtype = offtype self.segments = [] self.rawoff = [] self.geos_preprocessing(parent) self.make_segment_types() nextConvexPoint = [ e for e in self.segments if isinstance(e, ConvexPoint) ] # logger.debug(nextConvexPoint) # nextConvexPoint=[nextConvexPoint[31]] self.counter = 0 while len(nextConvexPoint): # [self.convex_vertex[-1]]: convex_vertex_nr = self.segments.index(nextConvexPoint[0]) # logger.debug(len(self.segments)) # logger.debug("convex_vertex: %s" % nextConvexPoint[0]) # logger.debug("convex_vertex_nr: %s" % convex_vertex_nr) forward, backward = self.PairWiseInterferenceDetection( convex_vertex_nr + 1, convex_vertex_nr - 1) # logger.debug("forward: %s, backward: %s" % (forward, backward)) if forward is None: return break if backward == 0 and forward == (len(self.segments) - 1) and self.closed: self.segments = [] break # Make Raw offset curve of forward and backward segment fw_rawoff_seg = self.make_rawoff_seg(self.segments[forward]) bw_rawoff_seg = self.make_rawoff_seg(self.segments[backward]) # Intersect the two segements iPoint = fw_rawoff_seg.find_inter_point(bw_rawoff_seg) if iPoint is None: logger.debug("fw_rawoff_seg: %s, bw_rawoff_seg: %s" % (fw_rawoff_seg, bw_rawoff_seg)) logger.debug( "forward: %s, backward: %s, iPoint: %s =====================================" % (forward, backward, iPoint)) logger.debug(fw_rawoff_seg) logger.debug(bw_rawoff_seg) logger.error("No intersection found?!") self.segments = [] # raise Exception("No intersection found?!") break # Reomve the LIR from the PS Curce self.remove_LIR(forward, backward, iPoint) nextConvexPoint = [ e for e in self.segments if isinstance(e, ConvexPoint) ] # logger.debug(nextConvexPoint) # nextConvexPoint=[] # logger.debug(nextConvexPoint) for seg in self.segments: self.rawoff += [self.make_rawoff_seg(seg)] def __str__(self): """ Standard method to print the object @return: A string """ return "\nnr: %i" % self.nr +\ "\nclosed: %s" % self.closed +\ "\ngeos: %s" % self.geos +\ "\nofftype: %s" % self.offtype +\ "\noffset: %s" % self.offset +\ "\nsegments: %s" % self.segments +\ "\nrawoff %s" % self.rawoff def geos_preprocessing(self, parent): """ Do all the preprocessing required in order to have working offset algorithm. @param parent: The parent shape including the geometries to be offsetted. """ self.geos = Geos([]) for geo in parent.geos: if isinstance(geo, LineGeo): self.geos.append(OffLineGeo().abscopy(geo, parent)) elif isinstance(geo, ArcGeo): self.geos.append(OffArcGeo().abscopy(geo, parent)) else: logger.error("Should not be here") logger.debug(self.geos) self.make_shape_ccw() self.join_colinear_lines() def make_segment_types(self): """ This function is called in order to generate the segements according to Definiton 2. An edge (line) is a linear segment and a reflex vertex is is reflex segment. Colinear lines are assumed to be removed prior to the segment type definition. """ # Do only if more then 2 geometies # if len(self.geos) < 2: # return # Start with first Vertex if the line is closed if self.closed: start = 0 else: start = 1 geo1 = self.geos[0] if isinstance(geo1, LineGeo): geo1.start_normal = geo1.Ps.get_normal_vector(geo1.Pe) geo1.end_normal = geo1.Ps.get_normal_vector(geo1.Pe) else: geo1.start_normal = geo1.O.unit_vector(geo1.Ps, r=1) geo1.end_normal = geo1.O.unit_vector(geo1.Pe, r=1) if geo1.ext < 0: geo1.start_normal = geo1.start_normal * -1 geo1.end_normal = geo1.end_normal * -1 self.segments += [geo1] for i in range(start, len(self.geos)): geo1 = self.geos[i - 1] geo2 = self.geos[i] if i == start: if isinstance(geo1, LineGeo): geo1.start_normal = geo1.Ps.get_normal_vector(geo1.Pe) geo1.end_normal = geo1.Ps.get_normal_vector(geo1.Pe) else: geo1.start_normal = geo1.O.unit_vector(geo1.Ps, r=1) geo1.end_normal = geo1.O.unit_vector(geo1.Pe, r=1) if geo1.ext < 0: geo1.start_normal = geo1.start_normal * -1 geo1.end_normal = geo1.end_normal * -1 if isinstance(geo2, LineGeo): geo2.start_normal = geo2.Ps.get_normal_vector(geo2.Pe) geo2.end_normal = geo2.Ps.get_normal_vector(geo2.Pe) elif isinstance(geo2, ArcGeo): geo2.start_normal = geo2.O.unit_vector(geo2.Ps, r=1) geo2.end_normal = geo2.O.unit_vector(geo2.Pe, r=1) if geo2.ext < 0: geo2.start_normal = geo2.start_normal * -1 geo2.end_normal = geo2.end_normal * -1 # logger.debug("geo1: %s, geo2: %s" % (geo1, geo2)) # logger.debug("geo1.end_normal: %s, geo2.start_normal: %s" % (geo1.end_normal, geo2.start_normal)) # If it is a reflex vertex add a reflex segemnt (single point) # Add a Reflex Point if radius becomes below zero. # if isinstance(geo2, ArcGeo): # logger.debug(geo2) # geo2_off = self.make_rawoff_seg(geo2) # logger.debug(geo2_off) # if ((isinstance(geo2, ArcGeo)) and ((self.offtype == "out" and geo2.ext > 0) or (self.offtype == "in" and geo2.ext < 0)) and ((geo2.r - abs(self.offset)) <= 0.0)): newgeo2 = ConvexPoint(geo2.O.x, geo2.O.y) newgeo2.start_normal = geo2.start_normal newgeo2.end_normal = geo2.end_normal geo2 = newgeo2 # logger.debug(geo1.Pe.ccw(geo1.Pe + geo1.end_normal, # geo1.Pe + geo1.end_normal + # geo2.start_normal)) # logger.debug(geo1) # logger.debug(geo2) # logger.debug(geo1.end_normal) # logger.debug(geo2.start_normal) if (((geo1.Pe.ccw(geo1.Pe + geo1.end_normal, geo1.Pe + geo1.end_normal + geo2.start_normal) == 1) and self.offtype == "in") or (geo1.Pe.ccw(geo1.Pe + geo1.end_normal, geo1.Pe + geo1.end_normal + geo2.start_normal) == -1 and self.offtype == "out")): # logger.debug("reflex") geo1.Pe.start_normal = geo1.end_normal geo1.Pe.end_normal = geo2.start_normal self.segments += [geo1.Pe, geo2] elif (geo1.Pe.ccw(geo1.Pe + geo1.end_normal, geo1.Pe + geo1.end_normal + geo2.start_normal) == 0): self.segments += [geo2] # Add the linear segment which is a line connecting 2 vertices else: # logger.debug("convex") self.segments += [ConvexPoint(geo1.Pe.x, geo1.Pe.y), geo2] # logger.debug("Self.segments: %s" % self.segments) # self.segments_plot = deepcopy(self.segments) def make_rawoff_seg(self, seg): """ This function returns the rawoffset of a segement. A line for a line and a circle for a reflex segement. @param segment_nr: The nr of the segement for which the rawoffset segement shall be generated @ return: Returns the rawoffsetsegement of the defined segment """ # seg=self.segments[segment_nr] if self.offtype == "out": offset = -abs(self.offset) else: offset = abs(self.offset) # if segement 1 is inverted change End Point if isinstance(seg, OffLineGeo): Ps = seg.Ps + seg.start_normal * offset Pe = seg.Pe + seg.end_normal * offset return OffLineGeo(Ps, Pe) elif isinstance(seg, OffPoint): Ps = seg + seg.start_normal * offset Pe = seg + seg.end_normal * offset return OffArcGeo(Ps=Ps, Pe=Pe, O=deepcopy(seg), r=self.offset, direction=offset) elif isinstance(seg, OffArcGeo): Ps = seg.Ps + seg.start_normal * offset Pe = seg.Pe + seg.end_normal * offset if seg.ext > 0: return OffArcGeo(Ps=Ps, Pe=Pe, O=seg.O, r=seg.r + offset, direction=seg.ext) else: return OffArcGeo(Ps=Ps, Pe=Pe, O=seg.O, r=seg.r - offset, direction=seg.ext) elif isinstance(seg, ConvexPoint): Ps = seg + seg.start_normal * offset Pe = seg + seg.end_normal * offset return OffArcGeo(Ps=Ps, Pe=Pe, O=deepcopy(seg), r=self.offset, direction=offset) else: logger.error("Unsupportet Object type: %s" % type(seg)) def interfering_full(self, segment1, dir, segment2): """ Check if the Endpoint (dependent on dir) of segment 1 is interfering with segment 2 Definition according to Definition 6 @param segment 1: The first segment @param dir: The direction of the line 1, as given -1 reversed direction @param segment 2: The second segment to be checked @ return: Returns True or False """ # if segement 1 is inverted change End Point if isinstance(segment1, OffLineGeo) and dir == 1: Pe = segment1.Pe elif isinstance(segment1, OffLineGeo) and dir == -1: Pe = segment1.Ps elif isinstance(segment1, ConvexPoint): return False elif isinstance(segment1, OffPoint): Pe = segment1 elif isinstance(segment1, OffArcGeo) and dir == 1: Pe = segment1.Pe elif isinstance(segment1, OffArcGeo) and dir == -1: Pe = segment1.Ps else: logger.error("Unsupportet Object type: %s" % type(segment1)) # if we cut outside reverse the offset if self.offtype == "out": offset = -abs(self.offset) else: offset = abs(self.offset) if dir == 1: distance = segment2.distance(Pe + segment1.end_normal * offset) # self.interferingshapes += [OffLineGeo(Pe, Pe + segment1.end_normal * offset), # segment2, # OffArcGeo(O=Pe + segment1.end_normal * offset, # Ps=Pe, Pe=Pe , # s_ang=0, e_ang=2 * pi, r=self.offset)] else: # logger.debug(Pe) # logger.debug(segment1) # logger.debug(segment1.start_normal) distance = segment2.distance(Pe + segment1.start_normal * offset) # self.interferingshapes += [OffLineGeo(Pe, Pe + segment1.start_normal * offset), # segment2, # OffArcGeo(O=Pe + segment1.start_normal * offset, # Ps=Pe, Pe=Pe, # s_ang=0, e_ang=2 * pi, r=self.offset)] # logger.debug("Full distance: %s" % distance) # If the distance from the Segment to the Center of the Tangential Circle # is smaller then the radius we have an intersection return distance <= abs(offset) def interfering_partly(self, segment1, dir, segment2): """ Check if any tangential circle of segment 1 is interfering with segment 2. Definition according to Definition 5 @param segment 1: The first Line @param dir: The direction of the segment 1, as given -1 reversed direction @param segment 2: The second line to be checked @ return: Returns True or False """ if isinstance(segment1, ConvexPoint): logger.debug("Should not be here") return False else: offGeo = self.make_rawoff_seg(segment1) # self.interferingshapes += [offGeo] # if we cut outside reverse the offset if self.offtype == "out": offset = -abs(self.offset) else: offset = abs(self.offset) # offGeo=LineGeo(Ps,Pe) # logger.debug(segment2) # logger.debug(offGeo) # logger.debug("Partly distance: %s" % segment2.distance(offGeo)) # If the distance from the Line to the Center of the Tangential Circle # is smaller then the radius we have an intersection return segment2.distance(offGeo) <= abs(offset) def Interfering_relation(self, segment1, segment2): """ Check the interfering relation between two segements (segment1 and segment2). Definition acccording to Definition 6 @param segment1: The first segment (forward) @param segment2: The second segment (backward) @return: Returns one of [full, partial, reverse, None] interfering relations for both segments """ # logger.debug("\nChecking: segment1: %s, \nsegment2: %s" % (segment1, segment2)) # Check if segments are equal if segment1 == segment2: return None, None if self.interfering_full(segment1, 1, segment2): self.interfering_partly(segment1, 1, segment2) L1_status = "full" elif self.interfering_partly(segment1, 1, segment2): L1_status = "partial" else: L1_status = "reverse" if self.interfering_full(segment2, -1, segment1): self.interfering_partly(segment2, -1, segment1) L2_status = "full" elif self.interfering_partly(segment2, -1, segment1): L2_status = "partial" else: L2_status = "reverse" # logger.debug("Start Status: L1_status: %s,L2_status: %s" % (L1_status, L2_status)) return [L1_status, L2_status] def PairWiseInterferenceDetection( self, forward, backward, ): """ Returns the first forward and backward segment nr. for which both interfering conditions are partly. @param foward: The nr of the first forward segment @param backward: the nr. of the first backward segment @return: forward, backward """ val = 2000 # self.counter = 0 L1_status, L2_status = "full", "full" # Repeat until we reached the Partial-interfering-relation while not (L1_status == "partial" and L2_status == "partial"): self.interferingshapes = [] self.counter += 1 if forward >= len(self.segments): forward = 0 segment1 = self.segments[forward] segment2 = self.segments[backward] if isinstance(segment1, ConvexPoint): forward += 1 if forward >= len(self.segments): forward = 0 segment1 = self.segments[forward] # logger.debug("Forward ConvexPoint") if isinstance(segment2, ConvexPoint): backward -= 1 segment2 = self.segments[backward] # logger.debug("Backward ConvexPoint") # logger.debug("Checking: forward: %s, backward: %s" % (forward, backward)) [L1_status, L2_status] = self.Interfering_relation(segment1, segment2) # logger.debug("Start Status: L1_status: %s,L2_status: %s" % (L1_status, L2_status)) """ The reverse interfering segment is replaced by the first non-reverse-interfering segment along it's tracking direction """ if L1_status == "reverse": while L1_status == "reverse": self.counter += 1 # logger.debug(self.counter) if self.counter > val: break if self.counter >= val: self.interferingshapes = [] forward += 1 if forward >= len(self.segments): forward = 0 segment1 = self.segments[forward] if isinstance(segment1, ConvexPoint): forward += 1 segment1 = self.segments[forward] # logger.debug("Forward ConvexPoint") # logger.debug("Reverse Replace Checking: forward: %s, backward: %s" %(forward, backward)) [L1_status, L2_status ] = self.Interfering_relation(segment1, segment2) # logger.debug("Checking: forward: %s, backward: %s" %(forward, backward)) # logger.debug("Replace Reverse: L1_status: %s,L2_status: %s" %(L1_status,L2_status)) elif L2_status == "reverse": while L2_status == "reverse": self.counter += 1 # logger.debug(self.counter) if self.counter > val: break if self.counter >= val: self.interferingshapes = [] backward -= 1 # logger.debug("Reveerse Replace Checking: forward: %s, backward: %s" %(forward, backward)) segment2 = self.segments[backward] if isinstance(segment2, ConvexPoint): backward -= 1 segment2 = self.segments[backward] # logger.debug("Backward ConvexPoint") [L1_status, L2_status ] = self.Interfering_relation(segment1, segment2) # logger.debug("Checking: forward: %s, backward: %s" %(forward, backward)) # logger.debug("Replace Reverse: L1_status: %s,L2_status: %s" %(L1_status,L2_status)) """ Full interfering segment is replaced by the nexst segemnt along the tracking direction. """ if L1_status == "full" and (L2_status == "partial" or L2_status == "full"): forward += 1 elif L2_status == "full" and (L1_status == "partial" or L1_status == "partial"): backward -= 1 # If The begin end point is the end end point we are done. if L1_status is None and L2_status is None: # logger.debug("Begin = End; Remove all") return len(self.segments) - 1, 0 # logger.debug(self.counter) # logger.debug("L1_status: %s,L2_status: %s" %(L1_status,L2_status)) if self.counter == val: self.interferingshapes = [] if self.counter > val: # 26: logger.error("No partial - partial status found") return None, None # logger.debug("Result: forward: %s, backward: %s" %(forward, backward)) return forward, backward def remove_LIR(self, forward, backward, iPoint): """ The instance is used to remove the LIR from the PS curve. @param forward: The forward segment of the LIR @param backward: The backward segement of the LIR @param iPoint: The Intersection point of the LIR """ if backward > forward: pop_range = self.segments[backward + 1:len(self.segments)] pop_range += self.segments[0:forward] elif backward < 0: pop_range = self.segments[len(self.segments) + backward + 1:len(self.segments)] pop_range += self.segments[0:forward] else: pop_range = self.segments[backward + 1:forward] if self.offtype == "out": rev = True else: rev = False # Modify the first segment and the last segment of the LIR self.segments[forward] = self.segments[forward].trim(Point=iPoint, dir=1, rev_norm=rev) self.segments[backward] = self.segments[backward].trim(Point=iPoint, dir=-1, rev_norm=rev) # Remove the segments which are inbetween the LIR self.segments = [x for x in self.segments if x not in pop_range]
def make_start_moves(self): """ This function called to create the start move. It will be generated based on the given values for start and angle. """ self.geos = Geos([]) if g.config.machine_type == 'drag_knife': self.make_swivelknife_move() return elif self.shape.cut_cor != 40 and not g.config.vars.Cutter_Compensation["done_by_machine"]: self.make_own_cutter_compensation() return # Get the start rad. and the length of the line segment at begin. start_rad = self.shape.parentLayer.start_radius # Get tool radius based on tool diameter. tool_rad = self.shape.parentLayer.getToolRadius() # Calculate the starting point with and without compensation. start = self.start angle = self.angle if self.shape.cut_cor == 40: self.append(RapidPos(start)) # Cutting Compensation Left elif self.shape.cut_cor == 41: # Center of the Starting Radius. Oein = start.get_arc_point(angle + pi/2, start_rad + tool_rad) # Start Point of the Radius Pa_ein = Oein.get_arc_point(angle + pi, start_rad + tool_rad) # Start Point of the straight line segment at begin. Pg_ein = Pa_ein.get_arc_point(angle + pi/2, start_rad) # Get the dive point for the starting contour and append it. start_ein = Pg_ein.get_arc_point(angle, tool_rad) self.append(RapidPos(start_ein)) # generate the Start Line and append it including the compensation. start_line = LineGeo(start_ein, Pa_ein) self.append(start_line) # generate the start rad. and append it. start_rad = ArcGeo(Ps=Pa_ein, Pe=start, O=Oein, r=start_rad + tool_rad, direction=1) self.append(start_rad) # Cutting Compensation Right elif self.shape.cut_cor == 42: # Center of the Starting Radius. Oein = start.get_arc_point(angle - pi/2, start_rad + tool_rad) # Start Point of the Radius Pa_ein = Oein.get_arc_point(angle + pi, start_rad + tool_rad) # Start Point of the straight line segment at begin. Pg_ein = Pa_ein.get_arc_point(angle - pi/2, start_rad) # Get the dive point for the starting contour and append it. start_ein = Pg_ein.get_arc_point(angle, tool_rad) self.append(RapidPos(start_ein)) # generate the Start Line and append it including the compensation. start_line = LineGeo(start_ein, Pa_ein) self.append(start_line) # generate the start rad. and append it. start_rad = ArcGeo(Ps=Pa_ein, Pe=start, O=Oein, r=start_rad + tool_rad, direction=0) self.append(start_rad)