Exemple #1
0
    def bulge2arc(self, Ps, Pe, bulge):
        """
        bulge2arc()
        """
        c = (1 / bulge - bulge) / 2

        #Berechnung des Mittelpunkts (Formel von Mickes!)
        #Calculation of the center (Micke's formula)
        O = Point(x=(Ps.x + Pe.x - (Pe.y - Ps.y) * c) / 2, \
                  y=(Ps.y + Pe.y + (Pe.x - Ps.x) * c) / 2)

        #Radius = Distance between the centre and Ps
        r = O.distance(Ps)
        #Kontrolle ob beide gleich sind (passt ...)
        #Check if they are equal (fits ...)
        #r=O.distance(Pe)

        #Unterscheidung f�r den �ffnungswinkel.
        #Distinction for the opening angle. ???
        if bulge > 0:
            return ArcGeo(Ps=Ps, Pe=Pe, O=O, r=r)
        else:
            arc = ArcGeo(Ps=Pe, Pe=Ps, O=O, r=r)
            arc.reverse()
            return arc
Exemple #2
0
    def fit_triac_by_inc_biarc(self, arc, eps):
        """
        fit_triac_by_inc_biarc()
        """

        #Errechnen von tb
        V0 = arc[0].Ps.unit_vector(arc[0].O)
        V2 = arc[2].Pe.unit_vector(arc[2].O)

        #Errechnen der Hilfgr�ssen
        t0 = (arc[2].r - arc[0].r)
        D = (arc[2].O - arc[0].O)
        X0 = (t0 * t0) - (D * D)
        X1 = 2 * (D * V0 - t0)
        Y0 = 2 * (t0 - D * V2)
        Y1 = 2 * (V0 * V2 - 1)

        #Errechnen von tb
        tb = (pow((arc[1].r - arc[0].r + eps), 2) - ((arc[1].O - arc[0].O) * (arc[1].O - arc[0].O))) / \
            (2 * (arc[1].r - arc[0].r + eps + (arc[1].O - arc[0].O) * V0))

        #Errechnen von tc
        tc = (pow(t0, 2) - (D * D)) / (2 * (t0 - D * V0))

        #Auswahl von t
        t = min([tb, tc])

        #Errechnen von u
        u = (X0 + X1 * t) / (Y0 + Y1 * t)

        #Errechnen der neuen Arcs
        Oa = arc[0].O + t * V0
        ra = arc[0].r + t
        Ob = arc[2].O - u * V2
        rb = arc[2].r - u
        Vn = Ob.unit_vector(Oa)
        Pn = Oa + ra * Vn

        Arc0 = ArcGeo(Ps=arc[0].Ps, Pe=Pn, O=Oa, r=ra, direction=arc[0].ext)
        Arc1 = ArcGeo(Ps=Pn, Pe=arc[2].Pe, O=Ob, r=rb, direction=arc[2].ext)

##        print('\nAlte')
##        print arc[0]
##        print arc[1]
##        print arc[2]
##        print("tb: %0.3f; tc: %0.3f; t: %0.3f; u: %0.3f" %(tb,tc,t,u))
##        print 'Neue'
##        print Arc0
##        print Arc1

        return Arc0, Arc1
Exemple #3
0
    def fit_triac_by_dec_biarc(self, arc, eps):
        """
        fit_triac_by_dec_biarc()
        """

        V0 = arc[2].Pe.unit_vector(arc[2].O)
        V2 = arc[0].Ps.unit_vector(arc[0].O)

        #Errechnen der Hilfgr�ssen
        t0 = (arc[0].r - arc[2].r)
        D = (arc[0].O - arc[2].O)
        X0 = (t0 * t0) - (D * D)
        X1 = 2 * (D * V0 - t0)
        Y0 = 2 * (t0 - D * V2)
        Y1 = 2 * (V0 * V2 - 1)

        #Errechnen von tb
        tb = (pow((arc[1].r - arc[2].r + eps), 2) - ((arc[1].O - arc[2].O) * (arc[1].O - arc[2].O))) / \
             (2 * (arc[1].r - arc[2].r + eps + (arc[1].O - arc[2].O) * V0))

        #Errechnen von tc
        tc = (pow(t0, 2) - (D * D)) / (2 * (t0 - D * V0))

        #Auswahl von t
        t = min([tb, tc])

        #Errechnen von u
        u = (X0 + X1 * t) / (Y0 + Y1 * t)

        #Errechnen der neuen Arcs
        Oa = arc[0].O - u * V2
        ra = arc[0].r - u
        Ob = arc[2].O + t * V0
        rb = arc[2].r + t
        Vn = Oa.unit_vector(Ob)
        Pn = Ob + rb * Vn

        Arc0 = ArcGeo(Ps=arc[0].Ps, Pe=Pn, O=Oa, r=ra, \
                    s_ang=Oa.norm_angle(arc[0].Ps), e_ang=Oa.norm_angle(Pn),
                    direction=arc[0].ext)
        Arc1 = ArcGeo(Ps=Pn, Pe=arc[2].Pe, O=Ob, r=rb, \
                    s_ang=Ob.norm_angle(Pn), e_ang=Ob.norm_angle(arc[2].Pe),
                    direction=arc[2].ext)

        return Arc0, Arc1
Exemple #4
0
 def breakArcGeo(self, arcGeo, breakLayers):
     """
     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 = []
     for breakLayer in breakLayers:
         for breakShape in breakLayer.shapes:
             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), breakLayers))
                 newGeos.append(
                     BreakGeo(near, far, breakLayer.axis3_mill_depth,
                              breakLayer.f_g1_plane, breakLayer.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), breakLayers))
                 return newGeos
     return [arcGeo]
    def bulge2arc(self, Pa, Pe, bulge):
        """
        bulge2arc()
        """
        c = (1 / bulge - bulge) / 2

        #Calculate the centre point (Micke's formula!)
        O = Point(x=(Pa.x + Pe.x - (Pe.y - Pa.y) * c) / 2, \
                  y=(Pa.y + Pe.y + (Pe.x - Pa.x) * c) / 2)

        #Radius = Distance between the centre and Pa
        r = O.distance(Pa)

        #Check if they are equal (fits ...)
        #r=O.distance(Pe)

        #Unterscheidung für den Öffnungswinkel.
        #Distinction for the opening angle. ???
        if bulge > 0:
            return ArcGeo(Pa=Pa, Pe=Pe, O=O, r=r)
        else:
            arc = ArcGeo(Pa=Pe, Pe=Pa, O=O, r=r)
            arc.reverse()
            return arc
    def bulge2arc(self, Ps, Pe, bulge):
        """
        bulge2arc()
        """
        c = (1 / bulge - bulge) / 2

        #Calculate the centre point (Micke's formula!)
        O = Point(x=(Ps.x + Pe.x - (Pe.y - Ps.y) * c) / 2, \
                  y=(Ps.y + Pe.y + (Pe.x - Ps.x) * c) / 2)

        #Radius = Distance between the centre and Ps
        r = O.distance(Ps)

        #Check if they are equal (fits ...)
        #r=O.distance(Pe)

        #Unterscheidung f�r den �ffnungswinkel.
        #Distinction for the opening angle. ???
        if bulge > 0:
            return ArcGeo(Ps=Ps, Pe=Pe, O=O, r=r)
        else:
            arc = ArcGeo(Ps=Pe, Pe=Ps, O=O, r=r)
            arc.reverse()
            return arc
Exemple #7
0
    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.LayerContent.tool_diameter / 2
        dragAngle = self.shape.dragAngle

        startnorm = offset * Point(1, 0, 0)
        prvend, prvnorm = Point(0, 0), Point(0, 0)
        first = 1

        #start = self.startp

        #Use The same parent as for the shape
        self.parent = self.shape.parent

        for geo in self.shape.geos:
            if geo.type == 'LineGeo':
                geo_b = deepcopy(geo)
                if first:
                    first = 0
                    prvend = geo_b.Pa + startnorm
                    prvnorm = startnorm
                norm = offset * geo_b.Pa.unit_vector(geo_b.Pe)
                geo_b.Pa += norm
                geo_b.Pe += norm
                if not prvnorm == norm:
                    swivel = ArcGeo(Pa=prvend,
                                    Pe=geo_b.Pa,
                                    r=offset,
                                    direction=prvnorm.cross_product(norm).z)
                    swivel.drag = dragAngle < abs(swivel.ext)
                    self.geos.append(swivel)
                self.geos.append(geo_b)

                prvend = geo_b.Pe
                prvnorm = norm
            elif geo.type == 'ArcGeo':
                geo_b = deepcopy(geo)
                if first:
                    first = 0
                    prvend = geo_b.Pa + 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.Pa += 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 not prvnorm == norma:
                    swivel = ArcGeo(Pa=prvend,
                                    Pe=geo_b.Pa,
                                    r=offset,
                                    direction=prvnorm.cross_product(norma).z)
                    swivel.drag = dragAngle < abs(swivel.ext)
                    self.geos.append(swivel)
                prvend = geo_b.Pe
                prvnorm = offset * norme
                if -pi < geo_b.ext < pi:
                    self.geos.append(
                        ArcGeo(Pa=geo_b.Pa,
                               Pe=geo_b.Pe,
                               r=sqrt(geo_b.r**2 + offset**2),
                               direction=geo_b.ext))
                else:
                    geo_b = ArcGeo(Pa=geo_b.Pa,
                                   Pe=geo_b.Pe,
                                   r=sqrt(geo_b.r**2 + offset**2),
                                   direction=-geo_b.ext)
                    geo_b.ext = -geo_b.ext
                    self.geos.append(geo_b)
            #else:
            #    self.geos.append(copy(geo))
        if not prvnorm == startnorm:
            self.geos.append(
                ArcGeo(Pa=prvend,
                       Pe=prvend - prvnorm + startnorm,
                       r=offset,
                       direction=prvnorm.cross_product(startnorm).z))

        self.geos.insert(0, self.geos[0].Pa)
Exemple #8
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.
        """
        del (self.geos[:])

        if g.config.machine_type == 'drag_knife':
            self.make_swivelknife_move()
            return

        #BaseEntitie created to add the StartMoves etc. This Entitie must not
        #be offset or rotated etc.
        BaseEntitie = EntitieContentClass(Nr=-1,
                                          Name='BaseEntitie',
                                          parent=None,
                                          children=[],
                                          p0=Point(x=0.0, y=0.0),
                                          pb=Point(x=0.0, y=0.0),
                                          sca=[1, 1, 1],
                                          rot=0.0)

        self.parent = BaseEntitie

        #Get the start rad. and the length of the line segment at begin.
        start_rad = self.shape.LayerContent.start_radius
        start_ver = start_rad

        #Get tool radius based on tool diameter.
        tool_rad = self.shape.LayerContent.tool_diameter / 2

        #Calculate the starting point with and without compensation.
        start = self.startp
        angle = self.angle

        if self.shape.cut_cor == 40:
            self.geos.append(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_ver)

            #Get the dive point for the starting contour and append it.
            start_ein = Pg_ein.get_arc_point(angle, tool_rad)
            self.geos.append(start_ein)

            #generate the Start Line and append it including the compensation.
            start_line = LineGeo(Pg_ein, Pa_ein)
            self.geos.append(start_line)

            #generate the start rad. and append it.
            start_rad = ArcGeo(Pa=Pa_ein,
                               Pe=start,
                               O=Oein,
                               r=start_rad + tool_rad,
                               direction=1)
            self.geos.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_ver)

            #Get the dive point for the starting contour and append it.
            start_ein = Pg_ein.get_arc_point(angle, tool_rad)
            self.geos.append(start_ein)

            #generate the Start Line and append it including the compensation.
            start_line = LineGeo(Pg_ein, Pa_ein)
            self.geos.append(start_line)

            #generate the start rad. and append it.
            start_rad = ArcGeo(Pa=Pa_ein,
                               Pe=start,
                               O=Oein,
                               r=start_rad + tool_rad,
                               direction=0)
            self.geos.append(start_rad)
Exemple #9
0
    def Read(self, caller):
        """
        Read()
        """

        #Assign short name
        lp = caller.line_pairs
        e = lp.index_code(0, caller.start + 1)

        #Assign layer
        s = lp.index_code(8, caller.start + 1)
        self.Layer_Nr = caller.Get_Layer_Nr(lp.line_pair[s].value)

        #X Value
        s = lp.index_code(10, s + 1)
        x0 = float(lp.line_pair[s].value)

        #Y Value
        s = lp.index_code(20, s + 1)
        y0 = float(lp.line_pair[s].value)

        #Radius
        s = lp.index_code(40, s + 1)
        r = float(lp.line_pair[s].value)

        #Searching for an extrusion direction
        s_nxt_xt = lp.index_code(230, s + 1, e)
        #If there is a extrusion direction given flip around x-Axis
        if s_nxt_xt != None:
            extrusion_dir = float(lp.line_pair[s_nxt_xt].value)
            logger.debug(
                self.tr('Found extrusion direction: %s') % extrusion_dir)
            if extrusion_dir == -1:
                x0 = -x0

        O = Point(x0, y0)

        #Calculate the start and end values of the circle without clipping
        s_ang = -3 * pi / 4
        m_ang = s_ang - pi
        e_ang = -3 * pi / 4

        #Calculate the start and end values of the arcs
        Pa = Point(x=cos(s_ang) * r, y=sin(s_ang) * r) + O
        Pm = Point(x=cos(m_ang) * r, y=sin(m_ang) * r) + O
        Pe = Point(x=cos(e_ang) * r, y=sin(e_ang) * r) + O

        #Annexes to ArcGeo class for geometry
        self.geo.append(
            ArcGeo(Pa=Pa,
                   Pe=Pm,
                   O=O,
                   r=r,
                   s_ang=s_ang,
                   e_ang=m_ang,
                   direction=-1))
        self.geo.append(
            ArcGeo(Pa=Pm,
                   Pe=Pe,
                   O=O,
                   r=r,
                   s_ang=m_ang,
                   e_ang=e_ang,
                   direction=-1))

        #Length corresponds to the length (circumference?) of the circle
        self.length = self.geo[-1].length + self.geo[-2].length

        #New starting value for the next geometry
        caller.start = s
Exemple #10
0
    def __init__(self, Ps=Point(), tan_a=0.0,
                  Pb=Point, tan_b=0.0, min_r=1e-6):
        """
        Std. method to initialise the class.
        @param Ps: Start Point for the Biarc
        @param tan_a: Tangent of the Start Point
        @param Pb: End Point of the Biarc
        @param tan_b: Tangent of the End Point
        @param min_r: The minimum radius of a arc section.
        """
        min_len = 1e-12       #Min Abstand f�r doppelten Punkt / Minimum clearance for double point
        min_alpha = 1e-4      #Winkel ab welchem Gerade angenommen wird inr rad / Angle for which it is assumed straight inr rad
        max_r = 5e3           #Max Radius ab welchem Gerade angenommen wird (5m) / Max radius is assumed from which line (5m)
        min_r = min_r         #Min Radius ab welchem nichts gemacht wird / Min radius beyond which nothing is done

        self.Ps = Ps
        self.tan_a = tan_a
        self.Pb = Pb
        self.tan_b = tan_b
        self.l = 0.0
        self.shape = None
        self.geos = []
        self.k = 0.0

        #Errechnen der Winkel, L�nge und Shape
        #Calculate the angle, length and shape
        norm_angle, self.l = self.calc_normal(self.Ps, self.Pb)

        alpha, beta, self.teta, self.shape = self.calc_diff_angles(norm_angle, \
                                                              self.tan_a, \
                                                              self.tan_b, \
                                                              min_alpha)

        if(self.l < min_len):
            self.shape = "Zero"

        elif(self.shape == "LineGeo"):
            #Erstellen der Geometrie
            #Create the geometry
            self.shape = "LineGeo"
            self.geos.append(LineGeo(self.Ps, self.Pb))
        else:
            #Berechnen der Radien, Mittelpunkte, Zwichenpunkt
            #Calculate the radii, midpoints Zwichenpunkt
            r1, r2 = self.calc_r1_r2(self.l, alpha, beta, self.teta)

            if (abs(r1) > max_r)or(abs(r2) > max_r):
                #Erstellen der Geometrie
                #Create the geometry
                self.shape = "LineGeo"
                self.geos.append(LineGeo(self.Ps, self.Pb))
                return

            elif (abs(r1) < min_r)or(abs(r2) < min_r):
                self.shape = "Zero"
                return

            O1, O2, k = self.calc_O1_O2_k(r1, r2, self.tan_a, self.teta)

            #Berechnen der Start und End- Angles f�r das drucken
            #Calculate the start and end angles for the print
            s_ang1, e_ang1 = self.calc_s_e_ang(self.Ps, O1, k)
            s_ang2, e_ang2 = self.calc_s_e_ang(k, O2, self.Pb)

            #Berechnen der Richtung und der Extend
            #Calculate the direction and extent
            dir_ang1 = (tan_a - s_ang1) % (-2 * pi)
            dir_ang1 -= ceil(dir_ang1 / (pi)) * (2 * pi)

            dir_ang2 = (tan_b - e_ang2) % (-2 * pi)
            dir_ang2 -= ceil(dir_ang2 / (pi)) * (2 * pi)


            #Erstellen der Geometrien
            #Create the geometries
            self.geos.append(ArcGeo(Ps=self.Ps, Pe=k, O=O1, r=r1, \
                                    s_ang=s_ang1, e_ang=e_ang1, direction=dir_ang1))
            self.geos.append(ArcGeo(Ps=k, Pe=self.Pb, O=O2, r=r2, \
                                    s_ang=s_ang2, e_ang=e_ang2, direction=dir_ang2))
Exemple #11
0
    def Read(self, caller):
        """
        Read()
        """
        #Assign short name
        lp = caller.line_pairs
        e = lp.index_code(0, caller.start + 1)

        #Assign layer
        s = lp.index_code(8, caller.start + 1)
        self.Layer_Nr = caller.Get_Layer_Nr(lp.line_pair[s].value)

        #X Value
        s = lp.index_code(10, s + 1)
        x0 = float(lp.line_pair[s].value)

        #Y Value
        s = lp.index_code(20, s + 1)
        y0 = float(lp.line_pair[s].value)
        O = Point(x0, y0)

        #Radius
        s = lp.index_code(40, s + 1)
        r = float(lp.line_pair[s].value)

        #Start angle
        s = lp.index_code(50, s + 1)
        s_ang = radians(float(lp.line_pair[s].value))

        #End angle
        s = lp.index_code(51, s + 1)
        e_ang = radians(float(lp.line_pair[s].value))

        #Searching for an extrusion direction
        s_nxt_xt = lp.index_code(230, s + 1, e)
        #If there is a extrusion direction given flip around x-Axis
        if s_nxt_xt != None:
            extrusion_dir = float(lp.line_pair[s_nxt_xt].value)
            logger.debug(
                self.tr('Found extrusion direction: %s') % extrusion_dir)
            if extrusion_dir == -1:
                x0 = -x0
                s_ang = s_ang + pi
                e_ang = e_ang + pi

        #Calculate the start and end points of the arcs
        Pa = Point(x=cos(s_ang) * r, y=sin(s_ang) * r) + O
        Pe = Point(x=cos(e_ang) * r, y=sin(e_ang) * r) + O

        #Anhängen der ArcGeo Klasse für die Geometrie
        #Annexes to ArcGeo class for geometry
        self.geo.append(
            ArcGeo(Pa=Pa,
                   Pe=Pe,
                   O=O,
                   r=r,
                   s_ang=s_ang,
                   e_ang=e_ang,
                   direction=1))

        #Länge entspricht der Länge des Kreises
        #Length is the length (circumference?) of the circle
        self.length = self.geo[-1].length

        #        logger.debug(self.geo[-1])

        #Neuen Startwerd für die nächste Geometrie zurückgeben
        #New starting value for the next geometry
        caller.start = s
Exemple #12
0
    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.LayerContent.tool_diameter/2
        dragAngle = self.shape.dragAngle

        startnorm = offset*Point(1, 0, 0)  # TODO make knife direction a config setting
        prvend, prvnorm = Point(), Point()
        first = 1

        #Use The same parent as for the shape
        self.parent = self.shape.parent

        for geo in self.shape.geos:
            if geo.type == 'LineGeo':
                geo_b = deepcopy(geo)
                if first:
                    first = 0
                    prvend = geo_b.Ps + startnorm
                    prvnorm = startnorm
                if geo_b.Ps != geo_b.Pe:  # TODO this "fix" should be done during import
                    norm = offset * geo_b.Ps.unit_vector(geo_b.Pe)
                    geo_b.Ps += norm
                    geo_b.Pe += norm
                    if not prvnorm == norm:
                        swivel = ArcGeo(Ps=prvend, Pe=geo_b.Ps, r=offset, direction=prvnorm.cross_product(norm).z)
                        swivel.drag = dragAngle < abs(swivel.ext)
                        self.geos.append(swivel)
                    self.geos.append(geo_b)

                    prvend = geo_b.Pe
                    prvnorm = norm
            elif geo.type == 'ArcGeo':
                geo_b = deepcopy(geo)
                if first:
                    first = 0
                    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:
                    swivel = ArcGeo(Ps=prvend, Pe=geo_b.Ps, r=offset, direction=prvnorm.cross_product(norma).z)
                    swivel.drag = dragAngle < abs(swivel.ext)
                    self.geos.append(swivel)
                prvend = geo_b.Pe
                prvnorm = offset*norme
                if -pi < geo_b.ext < pi:
                    self.geos.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.geos.append(geo_b)
            # TODO support different geos, or disable them in the GUI
            # else:
            #     self.geos.append(copy(geo))
        if not prvnorm == startnorm:
            self.geos.append(ArcGeo(Ps=prvend, Pe=prvend-prvnorm+startnorm, r=offset, direction=prvnorm.cross_product(startnorm).z))

        self.geos.insert(0, self.geos[0].Ps)