Ejemplo n.º 1
0
    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()
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
 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
Ejemplo n.º 4
0
    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()
Ejemplo n.º 5
0
    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()
Ejemplo n.º 6
0
 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
Ejemplo n.º 7
0
 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]
Ejemplo n.º 8
0
 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]
Ejemplo n.º 9
0
 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]
Ejemplo n.º 10
0
 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]
Ejemplo n.º 11
0
    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()
Ejemplo n.º 12
0
    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))
Ejemplo n.º 13
0
    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)
Ejemplo n.º 14
0
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))
Ejemplo n.º 15
0
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]
Ejemplo n.º 16
0
    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))
Ejemplo n.º 17
0
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))
Ejemplo n.º 18
0
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))
Ejemplo n.º 19
0
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]
Ejemplo n.º 20
0
    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)