def fromBaseWire(self, wire, height, deform, closed=True):
        """
        Create neck profile section wire
        """
        edge = wire.Edges[0]
        leftTop = edge.Vertexes[0].Point
        rightTop = edge.Vertexes[1].Point
        width = wire.Length
        widthRef = width / 2

        cent = edge.valueAt(widthRef)
        cent = Vector(cent.x, cent.y, height)
        curve = Part.BSplineCurve([
            leftTop,
            Vector(cent.x, cent.y - (cent.y - leftTop.y) * deform,
                   cent.z * 0.95), cent,
            Vector(cent.x, cent.y + (rightTop.y - cent.y) * deform,
                   cent.z * 0.95), rightTop
        ])

        if closed:
            a, b, c, d = [curve.parameter(p) for p in curve.discretize(4)]
            segments = [
                geom.bspSegment(curve, a, b),
                geom.bspSegment(curve, b, c),
                geom.bspSegment(curve, c, d),
                Part.LineSegment(rightTop, leftTop)
            ]
            return Part.Wire(Part.Shape(segments).Edges)
        else:
            return curve
Esempio n. 2
0
 def seg(x, z):
     middle = geom.wireFromPrim(
         [Part.LineSegment(Vector(x, 200, pos.z), Vector(x, -200, pos.z))])
     place(middle, pos, angle)
     section = geom.sectionSegment(contour, middle)
     if section:
         return geom.wireFromPrim([section])
Esempio n. 3
0
def getDefaultTopTransition(contour, pos, defaultTransitionLength):
    """Generate default transitionEnd if no custom reference is provided"""
    line = geom.wireFromPrim(
        Part.LineSegment(Vector(pos.x + defaultTransitionLength, -150, pos.z),
                         Vector(pos.x + defaultTransitionLength, 150, pos.z)))
    (d, vs, es) = line.Shape.distToShape(contour.Shape)
    if d < 1e-5 and len(vs) > 1:
        return Part.Wire(Part.Shape([Part.LineSegment(vs[0][0], vs[1][0])]))
Esempio n. 4
0
def getTransitionStart(pos, profile, offset):
    """Generate the first profile"""
    profile = profile.wireAt(abs(pos.x - offset), pos + Vector(-offset, 0, 0))
    curve = profile.Edges[0]
    c1, c2, c3 = geom.bspDiscretize(curve.Curve, 3)
    return geom.wireFromPrim([
        c1, c2, c3,
        Part.LineSegment(Vector(profile.Edges[1].Vertexes[0].Point),
                         Vector(profile.Edges[1].Vertexes[1].Point))
    ])
Esempio n. 5
0
def getPocketsCut(angle, pos, depth):
    """Create solid to cut pockets from the headstock"""
    pockets = App.ActiveDocument.getObject('Marz_Headstock_Pockets')
    if pockets:
        pockets = pockets.Shape.copy()
        if angle > 0:
            pockets.Placement = Placement(
                pos, Rotation(Vector(0, 1, 0), math.degrees(angle)))
        else:
            pockets.Placement = Placement(pos + Vector(0, 0, -depth),
                                          Rotation(Vector(0, 1, 0), 0))
        return pockets
 def __call__(self, width, height):
     """
     Create neck profile section wire
     """
     leftTop = Vector(0, width / 2, 0)
     rightTop = Vector(0, -width / 2, 0)
     h = self.getHPoint(
         width, height)  # Vector(-height, width * self.h1Offset/2, 0)
     hl = Vector(-height * self.h2, width * self.h2Offset / 2, 0)
     hr = Vector(-height * self.h2, -width * self.h2Offset / 2, 0)
     points = [leftTop, hl, h, hr, rightTop]
     curve = Part.BSplineCurve()
     curve.interpolate(points)
     endl = Part.LineSegment(points[-1], points[0])
     return Part.Wire(Part.Shape([curve, endl]).Edges)
Esempio n. 7
0
def isTransitionWireValid(ref, wire):
    """Chech if {wire} is not inside ref or shrinks the loft"""
    cp = wire.copy()
    cp.translate(Vector(ref.CenterOfMass.x - wire.CenterOfMass.x, 0, 0))
    dist, vectors, edges = ref.distToShape(cp)
    n = len(edges)
    return dist > 1e-5 or n == 2 or n == 32
Esempio n. 8
0
def fretboardSection(c, r, w, t, v):
    """
    Creates a Wire for a Fretboard Loft
    c: center Vector
    r: Radius float
    w: Width float
    t: Thickness float
    v: Direction Vector
    """

    # Half angle of the top Arc
    alpha = math.asin(w/(2*r))
    alpha_deg = todeg(alpha)
    
    # Guess top Arc
    arc = Part.makeCircle(r, c, v, -alpha_deg, alpha_deg)
    
    # If arc fails: Guess at 90deg
    if arc.Vertexes[0].Point.z <= 0:
        arc = Part.makeCircle(r, c, v, 90-alpha_deg, 90+alpha_deg)
    
    # If arc fails again: Impossible
    if arc.Vertexes[0].Point.z <= 0:
        raise ModelException("Current Fretboard's radius is inconsistent with Fretboard's geometry")

    # Arc end points
    a = arc.Vertexes[0].Point
    b = arc.Vertexes[1].Point

    # Side fretboard height
    h = r * math.cos(alpha) - r + t

    # Fretboard bottom at side a
    x = Vector(a.x, a.y, a.z -h)

    # Fretboard bottom at side b
    d = Vector(b.x, b.y, b.z -h)

    # Fretboard top at center
    p = Vector(c.x, c.y, c.z +r)

    # Finally, the wire: arc(ba) -> seg(ax) -> seg(xd) -> seg(db)
    return Part.Wire(Part.Shape([
        Part.Arc(a,p,b), 
        Part.LineSegment(a,x), 
        Part.LineSegment(x,d), 
        Part.LineSegment(d,b)]).Edges)
Esempio n. 9
0
 def wire(i):
     l = i * step
     h = fnHeight(l)
     point = Vector(points[i].x, points[i].y, points[i].z)
     if angle != 0:
         point.z = -l * math.tan(angle)
     if useProfileTransition:
         progress = l / length
         w = fnWidth(i)
         p = fnProfile.transition(w, h, i, l / length, length,
                                  lastHeight)
         if p: p.Placement = Placement(point, rot)
     else:
         w = fnWidth(l)
         p = fnProfile(w, h)
         if p: p.Placement = Placement(point, rot)
     return p
Esempio n. 10
0
 def heelBase():
     segments = [
         Part.LineSegment(geom.vec(b), geom.vec(c)),
         Part.LineSegment(geom.vec(c), geom.vec(d)),
         Part.LineSegment(geom.vec(d), geom.vec(a)),
         Part.LineSegment(geom.vec(a), geom.vec(b)),
     ]
     part = Part.Face(Part.Wire(Part.Shape(segments).Edges)).extrude(
         Vector(0, 0, -100))
     return part
Esempio n. 11
0
def makeTenon(fbd, neckAngleRad, posXY, h, tenonThickness, tenonLength,
              tenonOffset, joint):
    if tenonThickness > 0 \
        and tenonLength > 0 \
            and joint is NeckJoint.SETIN:

        naLineDir = linexy(vxy(0, 0),
                           angleVxy(math.pi + neckAngleRad, tenonLength))
        naAp = geom.vecxz(naLineDir.start)
        naBp = geom.vecxz(naLineDir.end)
        refp = geom.vec(posXY, tenonOffset - h + tenonThickness)
        naSidePs = [
            naAp,
            Vector(naAp.x, naAp.y, naAp.z - tenonThickness),
            Vector(naBp.x, naBp.y, naBp.z - tenonThickness), naBp, naAp
        ]
        naSidePs = [v.add(refp) for v in naSidePs]
        naSide = Part.Face(Part.makePolygon(naSidePs)).extrude(
            Vector(0, fbd.neckFrame.bridge.length, 0))
        return naSide
Esempio n. 12
0
def flatTopCut(pos, depth, transitionLength, voluteOffset):
    """Create solid to cleanup the top surface"""
    a = Vector(pos)
    b = Vector(a.x + transitionLength + depth, a.y, a.z - depth)
    c = Vector(a.x + 300, b.y, b.z)
    d = Vector(c.x, c.y, c.z + 2 * depth)
    e = Vector(a.x - voluteOffset - 5, a.y, d.z)
    f = Vector(e.x, e.y, a.z)
    curve = Part.BSplineCurve([
        a,
        Vector(a.x + transitionLength / 2, a.x, a.z),
        Vector(a.x + transitionLength / 2, a.x, a.z - depth), b
    ])
    l1 = Part.LineSegment(b, c)
    l2 = Part.LineSegment(c, d)
    l3 = Part.LineSegment(d, e)
    l4 = Part.LineSegment(e, f)
    l5 = Part.LineSegment(f, a)
    wire = geom.wireFromPrim([curve, l1, l2, l3, l4, l5])
    wire.translate(Vector(0, -150, 0))
    wire = Part.Face(wire).extrude(Vector(0, 300, 0))
    return wire
Esempio n. 13
0
def getTransitionCurve(startProfile, end, height, hLerp, angle, profile, pos,
                       voluteOffset):
    """
    Generate mid points of the transition.
    Returns:
        Vector[] -- List of mid points for transition using bspline curve.
    """

    # Search start point
    pos = Vector(pos.x - voluteOffset, pos.y, pos.z)  # ! TODO: Barrel Slope
    s = profile.hPointAt(abs(pos.x), pos).Vertexes[0].Point
    c = end.CenterOfMass
    length = c.x - pos.x

    # Horizontal Ref
    hl = Part.LineSegment(
        Vector(s),
        Vector(c.x, c.y, s.z)  # ! TODO: Barrel Slope
    )

    # Vertical Ref
    vbz = c.z - height - end.Length
    hbx = length * hLerp

    # Bezier
    curve = Part.BSplineCurve(
        [hl.value(0), hl.value(hbx),
         Vector(c.x, s.y, vbz)])

    # Nearest end vertex
    a = end.Edges[0].Vertexes[0].Point
    b = end.Edges[0].Vertexes[1].Point
    p = a if a.x < b.x else b
    limit = p.x

    # Generate points
    points = [w for w in curve.discretize(20) if w.x > s.x and w.x < limit]
    return points, vbz, hbx
Esempio n. 14
0
def makeTransition(edge,
                   fnProfile,
                   fnWidth,
                   fnHeight,
                   steps=10,
                   limits=None,
                   solid=True,
                   ruled=True,
                   useProfileTransition=False,
                   angle=0,
                   lastHeight=40):
    with traceTime("Prepare transition geometry"):
        curve = edge.Curve
        points = edge.discretize(Number=steps + 1)
        direction = curve.Direction
        length = edge.Length
        step = length / steps
        rot = Rotation(Vector(0, 0, 1), direction)

        def wire(i):
            l = i * step
            h = fnHeight(l)
            point = Vector(points[i].x, points[i].y, points[i].z)
            if angle != 0:
                point.z = -l * math.tan(angle)
            if useProfileTransition:
                progress = l / length
                w = fnWidth(i)
                p = fnProfile.transition(w, h, i, l / length, length,
                                         lastHeight)
                if p: p.Placement = Placement(point, rot)
            else:
                w = fnWidth(l)
                p = fnProfile(w, h)
                if p: p.Placement = Placement(point, rot)
            return p

        wires = [wire(i) for i in range(steps + 1)]
        wires = [w for w in wires if w is not None]

    with traceTime("Make transition solid"):
        loft = Part.makeLoft(wires, solid, not useProfileTransition)

    if limits:
        with traceTime("Apply transition limits"):
            loft = limits.common(loft)

    return loft
Esempio n. 15
0
def voluteCutCylinder(radius, end, thickness, angle):
    """Generate solid to cut from the bottom of the construction"""
    length = end.Length
    pnt = end.Edges[0].Curve.value(-5)
    pnt = Vector(pnt.x, pnt.y, pnt.z - thickness * math.cos(angle))
    pnt = Vector(pnt.x - radius * math.sin(angle), pnt.y,
                 pnt.z - radius * math.cos(angle))
    cyl = Part.makeCylinder(radius, length + 10, pnt,
                            end.Edges[0].Curve.Direction)
    pnt2 = pnt + end.Edges[0].Curve.Direction * (length + 10)
    rec = Part.makePolygon([
        pnt + Vector(-radius, 0, 0), pnt2 + Vector(-radius, 0, 0),
        pnt2 + Vector(radius, 0, 0), pnt + Vector(radius, 0, 0),
        pnt + Vector(-radius, 0, 0)
    ])
    rec = Part.Face(rec)
    rec = rec.extrude(Vector(0, 0, -max(radius, 200)))
    solid = cyl.fuse(rec)
    return solid
Esempio n. 16
0
def angledTopCut(pos, angle, voluteOffset):
    """Create solid to cleanup the top surface"""
    a = Vector(pos)
    c = Vector(a.x + 300 * math.cos(angle), a.y, a.z - 300 * math.sin(angle))
    d = Vector(c.x, c.y, abs(c.z))
    e = Vector(a.x - voluteOffset - 5, a.y, d.z)
    f = Vector(e.x, e.y, a.z)
    l1 = Part.LineSegment(a, c)
    l2 = Part.LineSegment(c, d)
    l3 = Part.LineSegment(d, e)
    l4 = Part.LineSegment(e, f)
    l5 = Part.LineSegment(f, a)
    wire = geom.wireFromPrim([l1, l2, l3, l4, l5])
    wire.translate(Vector(0, -150, 0))
    solid = Part.Face(wire).extrude(Vector(0, 300, 0))
    return solid
Esempio n. 17
0
    def createConstructionShapesParts(self):
        placement = App.Placement()
        placement.Rotation.Q = (0,0,0,1)
        placement.Base = Vector(0,0,0)

        def createInUI():
            group = getUIGroup(UIGroup_XLines)
            for suffix, points, color in self.createConstructionShapes():
                part = findDraftByLabel(suffix)
                if part is None:
                    wire = Draft.makeWire(points, placement=placement, face=False)
                    wire.Label = suffix
                    Draft.autogroup(wire)
                    obj = findDraftByLabel(wire.Label)
                    obj.ViewObject.LineColor = color
                    group.addObject(obj)

        UIThread.run(createInUI)
Esempio n. 18
0
def getDefaultTop(pos, width, length, profile, angle, transitionLength):
    """Generate default contour and transitionEnd if no custom reference is provided"""
    startWidth = profile.widthAt(pos.x)
    a = Vector(pos.x, pos.y - startWidth / 2, pos.z)
    b = Vector(pos.x, pos.y + startWidth / 2, pos.z)
    c = Vector(b.x + transitionLength, b.y, b.z)
    d = Vector(c.x, pos.y + width / 2, c.z)
    e = Vector(d.x + length, d.y, d.z)
    f = Vector(e.x, e.y - width, e.z)
    g = Vector(f.x - length, f.y, f.z)
    h = Vector(g.x, a.y, g.z)
    l1 = Part.LineSegment(a, b)
    c2 = Part.BSplineCurve([b, c, d])
    l3 = Part.LineSegment(d, e)
    l4 = Part.LineSegment(e, f)
    l5 = Part.LineSegment(f, g)
    c6 = Part.BSplineCurve([g, h, a])
    contour = geom.wireFromPrim([l1, c2, l3, l4, l5, c6])
    transition = geom.wireFromPrim([Part.LineSegment(g, d)])
    return (place(contour, pos, angle), place(transition, pos, angle))
Esempio n. 19
0
def makeInlays(fbd, thickness, inlayDepth):

    line = fbd.scaleFrame.midLine
    shapes = []

    with traceTime("Prepare inlay pockets geometry"):
        for i in range(len(fbd.frets)):
            inlay = App.ActiveDocument.getObject(f"Marz_FInlay_Fret{i}")
            if inlay:
                ishape = inlay.Shape.copy()
                ishape.translate(fretPos(i, line, thickness))
                shapes.append(ishape)
    
    comp = None
    with traceTime("Build inlay pockets substractive solid"):
        if shapes:
            comp = Part.makeCompound(shapes).extrude(Vector(0, 0, -inlayDepth-1))
    
    return comp
Esempio n. 20
0
 def headstock(self, neckd, line):
     params = self.instrument.headStock
     profile = getNeckProfile(neckd.profileName)
     boundProfile = hs.BoundProfile(profile, neckd.fbd.widthAt,
                                    neckd.thicknessAt)
     pos = Vector(line.start.x, line.start.y, 0)
     return hs.build(pos,
                     deg(params.angle),
                     boundProfile,
                     params.thickness,
                     params.transitionParamHorizontal,
                     params.voluteRadius,
                     params.voluteOffset,
                     params.depth,
                     params.topTransitionLength,
                     params.width,
                     params.length,
                     indirectDependencies={
                         'svg': self.instrument.internal.headstockImport
                     })
Esempio n. 21
0
def extrudeBlank(top, thickness, angle, end, pos):
    """Generate base plate solid with transition space removed"""
    center = end.CenterOfMass
    extrusion = Vector(0, 0, -thickness * math.cos(angle))
    blank = Part.Face(top).extrude(extrusion)
    a = end.Edges[0].Vertexes[0].Point
    b = end.Edges[0].Vertexes[1].Point
    if a.y < b.y: a, b = b, a
    points = [
        Vector(pos.x, -100, 5),
        Vector(pos.x, 100, 5),
        Vector(a.x, a.y, 5),
        Vector(b.x, b.y, 5),
        Vector(pos.x, -100, 5)
    ]
    wire = Part.Wire(Part.makePolygon(points))
    wire.fixWire()
    cut = Part.Face(wire).extrude(Vector(0, 0, -200))
    return blank.cut(cut)
Esempio n. 22
0
def voluteCutFlat(pos, thickness, depth, angle, voluteOffset):
    """Generate solid to cut from the bottom of the construction"""
    width = 150
    length = 300
    pol = Part.makePolygon([
        Vector(pos.x - voluteOffset, -width, pos.z),
        Vector(pos.x - voluteOffset, width, pos.z),
        Vector(pos.x + length * math.cos(angle), width,
               pos.z - length * math.sin(angle)),
        Vector(pos.x + length * math.cos(angle), -width,
               pos.z - length * math.sin(angle)),
        Vector(pos.x - voluteOffset, -width, pos.z)
    ])
    height = (thickness + (0 if angle > 0 else depth)) * math.cos(angle)
    height = height - voluteOffset * math.sin(angle)
    pol.translate(Vector(0, 0, -height))
    wire = geom.wireFromPrim(pol)
    solid = Part.Face(wire).extrude(Vector(0, 0, -400))
    return solid
Esempio n. 23
0
def heelTransition(neckd, line, startd, h, transitionLength,
                   transitionTension):
    """
    Create transition from neck to heel shape.

    Args:
        neckd  : NeckData
        line   : linexy, reference line
        startd : starting point distance from line.start
        h      : Heel height
    """

    with traceTime("Make Heel Transition"):
        if transitionLength <= 0 or transitionTension <= 0:
            return None

        trline = linexy(line.lerpPointAt(startd),
                        line.lerpPointAt(startd + transitionLength * 2))
        length = trline.length
        Transition = transitionDatabase[neckd.transitionFunction]
        transition = Transition(neckd.widthAt, neckd.thicknessAt,
                                transitionTension, transitionTension, startd,
                                length)
        profile = getNeckProfile(neckd.profileName)
        wire = Part.Wire(
            Part.LineSegment(geom.vec(trline.start),
                             geom.vec(trline.end)).toShape())
        steps = int(trline.length / 4) + 1

        limit = geom.extrusion(neckd.fbd.neckFrame.polygon, 0,
                               Vector(0, 0, -h))
        tr = geom.makeTransition(wire.Edges[0],
                                 profile,
                                 transition.width,
                                 transition.height,
                                 steps=steps,
                                 limits=limit,
                                 ruled=False)

        return tr
Esempio n. 24
0
def makeHeel(neckd, line, angle, joint, backThickness, topThickness, topOffset,
             neckPocketDepth, neckPocketLength, jointFret, transitionLength,
             transitionTension, bodyLength, tenonThickness, tenonLength,
             tenonOffset, forPocket):
    """
    Create heel shape.

    Args:
        fbd   : FredboardData
        line  : linexy, reference line
    """
    fbd = neckd.fbd
    neckAngleRad = deg(angle)
    if joint is NeckJoint.THROUHG:
        h = backThickness + topThickness + topOffset
    else:
        h = neckPocketDepth + topOffset

    if forPocket:
        jointFret = 0

    start_p = lineIntersection(fbd.frets[jointFret], line).point
    start_d = linexy(line.start, start_p).length

    # Curved Part
    if not forPocket:
        transitionJob = Task.execute(heelTransition, neckd, line, start_d, h,
                                     transitionLength, transitionTension)

    xperp = line.lerpLineTo(
        start_d + transitionLength).perpendicularCounterClockwiseEnd()
    a = lineIntersection(xperp, fbd.neckFrame.treble).point
    b = lineIntersection(xperp, fbd.neckFrame.bass).point
    c = fbd.neckFrame.bridge.end
    d = fbd.neckFrame.bridge.start

    # Rect Part
    def heelBase():
        segments = [
            Part.LineSegment(geom.vec(b), geom.vec(c)),
            Part.LineSegment(geom.vec(c), geom.vec(d)),
            Part.LineSegment(geom.vec(d), geom.vec(a)),
            Part.LineSegment(geom.vec(a), geom.vec(b)),
        ]
        part = Part.Face(Part.Wire(Part.Shape(segments).Edges)).extrude(
            Vector(0, 0, -100))
        return part

    partJob = Task.execute(heelBase)

    if not forPocket:
        transition = transitionJob.get()
    else:
        transition = None

    part = partJob.get()

    if transition:
        part = transition.fuse(part)

    # Neck Angle Cut (Bottom)
    extrusionDepth = 100
    lengthDelta = max(neckPocketLength,
                      (fbd.neckFrame.midLine.length -
                       start_d))  #- inst.neck.transitionLength/2
    naLineDir = linexy(vxy(0, 0), angleVxy(neckAngleRad, lengthDelta))
    naLineDir = naLineDir.flipDirection().lerpLineTo(naLineDir.length +
                                                     30).flipDirection()
    naAp = geom.vecxz(naLineDir.start)
    naBp = geom.vecxz(naLineDir.end)
    refp = geom.vec(fbd.frame.bridge.end,
                    -h).add(Vector(0, -fbd.neckFrame.bridge.length / 2, 0))

    if joint is NeckJoint.THROUHG:
        refp = refp.add(
            Vector(-bodyLength * math.cos(neckAngleRad), 0,
                   -bodyLength * math.sin(neckAngleRad)))

    naSidePs = [
        naAp,
        Vector(naAp.x, naAp.y, naAp.z - extrusionDepth),
        Vector(naBp.x, naBp.y, naBp.z - extrusionDepth), naBp, naAp
    ]
    naSidePs = [v.add(refp) for v in naSidePs]
    naSide = Part.Face(Part.makePolygon(naSidePs)).extrude(
        Vector(0, fbd.neckFrame.bridge.length * 2, 0))

    # Cut bottom
    part = part.cut(naSide)

    # Then move and cut top (Remove Top thickness)
    cutThickness = extrusionDepth * math.cos(neckAngleRad)
    naSide.translate(
        Vector((backThickness + cutThickness) * math.sin(neckAngleRad), 0,
               (backThickness + cutThickness) * math.cos(neckAngleRad)))
    naSide.translate(
        Vector((bodyLength - lengthDelta) * math.cos(neckAngleRad), 0,
               (bodyLength - lengthDelta) * math.sin(neckAngleRad)))

    part = part.cut(naSide)

    # Tenon
    tenon = makeTenon(fbd, neckAngleRad, d, h,
                      tenonThickness + 100 if forPocket else tenonThickness,
                      tenonLength, tenonOffset, joint)
    if tenon:
        part = part.fuse(tenon)

    return part.removeSplitter()
Esempio n. 25
0
def vecyz(v, x=0):
    return Vector(x, v.x, v.y)
Esempio n. 26
0
def vecxz(v, y=0):
    return Vector(v.x, y, v.y)
Esempio n. 27
0
def extrusion(vs, z, dir):
    return face(vs, z).extrude(Vector(dir[0], dir[1], dir[2]))
Esempio n. 28
0
def vec(v, z=0):
    """Convert vxy to Vector"""
    return Vector(v.x, v.y, z)
Esempio n. 29
0
def place(shape, pos, angle):
    """Porition a shape to pos and rotation"""
    shape.translate(pos)
    shape.rotate(Vector(0, 0, 0), Vector(0, 1, 0), math.degrees(angle))
    return shape
Esempio n. 30
0
 def getHPoint(self, width, height):
     return Vector(-height, width * self.h1Offset / 2, 0)