Ejemplo n.º 1
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
Ejemplo n.º 2
0
def trussRodChannel(line, start, length, width, depth, headLength, headWidth,
                    headDepth, tailLength, tailWidth, tailDepth):

    with traceTime("Make Truss Rod Channel"):
        if length <= 0 or width <= 0 or depth <= 0:
            return None

        cutOffsetZ = 5

        # Base Channel
        base = linexy(line.lerpPointAt(start),
                      line.lerpPointAt(start + length)).rectSym(width)
        base = geom.extrusion(base, cutOffsetZ, (0, 0, -depth - cutOffsetZ))

        # Head
        if headLength > 0 and headWidth > 0 and headDepth > 0:
            head = linexy(line.lerpPointAt(start),
                          line.lerpPointAt(headLength +
                                           start)).rectSym(headWidth)
            head = geom.extrusion(head, cutOffsetZ,
                                  (0, 0, -headDepth - cutOffsetZ))
            base = base.fuse(head)

        # Tail
        if tailLength > 0 and tailWidth > 0 and tailDepth > 0:
            tail = linexy(line.lerpPointAt(start + length - tailLength),
                          line.lerpPointAt(start + length)).rectSym(tailWidth)
            tail = geom.extrusion(tail, cutOffsetZ,
                                  (0, 0, -tailDepth - cutOffsetZ))
            base = base.fuse(tail)

        return base
Ejemplo n.º 3
0
def base(inst, fbd): 
    """
    Create Fretboard base board
    """
    (board, cache) = getCachedObject('fretboard_base', fbd, inst.fretboard.startRadius, inst.fretboard.endRadius, inst.fretboard.thickness)
    if not board:
        with traceTime("Build fretboard base"):
            cone = fretboardCone(
                inst.fretboard.startRadius, 
                inst.fretboard.endRadius, 
                inst.fretboard.thickness, 
                fbd, 
                inst.fretboard.thickness
            )
            f = fbd.frame
            ps = [
                f.bridge.start,
                f.bass.start,
                f.nut.start,
                f.treble.start,
                f.bridge.start
            ]
            cut = geom.extrusion(ps, 0, (0,0,inst.fretboard.thickness+1))
            board = cone.common(cut)
        cache(board)
    return board
Ejemplo n.º 4
0
def fretsCutPure(startRadius, endRadius, thickness, tangDepth, tangWidth, nipping, isZeroFret, fbd):
    """
    Create a Solid with all frets to be cutted from board
    """
    jobs = []
    bladeHeight = thickness*4

    # Generate Cone
    trim = fretboardCone(
        startRadius, 
        endRadius, 
        thickness, 
        fbd, 
        thickness - tangDepth
    )

    # Generate Fret extrusions
    with traceTime('Generate all Fret slots'):
        frets = []
        for index, fret_i in enumerate(fbd.frets):
            # Zero fret visibility
            if not isZeroFret and index == 0:
                continue
            # Adjust Fret Size
            fret = fret_i.extendSym(-nipping if nipping > 0 else 5)
            # Extrude Fret
            blade = geom.extrusion(fret.rectSym(tangWidth), 0, [0,0,bladeHeight])
            blade = blade.cut(trim)
            frets.append(blade)
        return frets
Ejemplo n.º 5
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
Ejemplo n.º 6
0
def nutSlotPure(thickness, depth, fbd): 
    """
    Create a Nut Solid to be cutted from board
    """
    # Extend the nut frame to bleeding cut
    with traceTime("Nut slot solid"):
        nut = fbd.nutFrame.nut.clone().extendSym(5)
        bridge = fbd.nutFrame.bridge.clone().extendSym(5)
        polygon = [bridge.end, bridge.start, nut.end, nut.start, bridge.end] 
        return geom.extrusion(polygon, thickness - depth, [0,0,thickness*4])
Ejemplo n.º 7
0
def fretboardCone(startRadius, endRadius, thickness, fbd, top):
    """
    Create a Compund radius solid, result is oriented along `fbd.neckFrame.midLine` with top edge horizontal at z=`top`
    Args:
        inst : Instrument Data
        fbd  : FraneboardData
        top  : Top reference position
    """

    # Cone direction
    line = fbd.neckFrame.midLine
    
    # Slope calculated with radiuses at fret0 and fret12
    radiusSlope = (endRadius - startRadius) / (fbd.scaleFrame.midLine.length/2)

    # b = Distance from fret0 to neck start
    b = linexy(lineIntersection(line, fbd.frets[0]).point, line.start).length

    # Radius at l
    def radiusFn(l):
        return radiusSlope * (l + b) + startRadius

    # Center at l
    def centerFn(l, r):
        p = line.lerpPointAt(l)
        return Vector(p.x, p.y, top - r)

    # Wires for the Loft
    with traceTime("Prepare fretboad conic geometry"):
        wires = []
        vdir = geom.vec(line.vector)
        for (l, width) in [(0, fbd.neckFrame.nut.length), (line.length, fbd.neckFrame.bridge.length)]:
            radius = radiusFn(l)
            center = centerFn(l, radius)
            wire = fretboardSection(center, radius, width, thickness, vdir)
            wires.append(wire)

    # Solid
    with traceTime("Make fretboad conic solid"):
        solid = Part.makeLoft(wires, True, True).removeSplitter()

    return solid
Ejemplo n.º 8
0
    def createShape(self):
        """
        Create complete neck shape
        """
        inst = self.instrument
        fbd = builder.buildFretboardData(inst)
        neckd = NeckData(inst, fbd)

        # Extrusion Line (Nut -> Bridge)
        line = fbd.neckFrame.midLine

        # Barrel extrusion
        barrellJob = Task.execute(barrel, neckd, inst.neck.jointFret)

        # HeadStock blank
        headstockJob = Task.execute(self.headstock, neckd, line)

        # Heel
        heelJob = Task.execute(self.heel, neckd, line)

        # Truss Rod Channel
        trc = inst.trussRod
        trussRodJob = Task.execute(
            trussRodChannel, line, trc.start, trc.length, trc.width, \
                trc.depth, trc.headLength, trc.headWidth, trc.headDepth, \
                    trc.tailLength, trc.tailWidth, trc.tailDepth)

        with traceTime("Wait for Barrel + Heel + Headstock"):
            (barrellSolid, headstock, heel, truss) = Task.joinAll(
                [barrellJob, headstockJob, heelJob, trussRodJob])

        with traceTime("Fuse Barrel + Heel + Headstock"):
            neck = barrellSolid.fuse([headstock, heel])

        with traceTime("Carve truss rod channel"):
            if truss:
                neck = neck.cut(truss)

        neck.fix(0.1, 0, 1)
        return neck.removeSplitter()
Ejemplo n.º 9
0
    def createFretboardShape(self):
        """Create a Fretboard."""

        # Calculate model
        with traceTime('Calc Model'):
            inst = self.instrument
            fbd = builder.buildFretboardData(self.instrument)
        
        inlaysTask = Task.execute(makeInlays, fbd, inst.fretboard.thickness, inst.fretboard.inlayDepth)

        (fretboard, cache) = getCachedObject('FretboardFeature', 
            fbd, inst.fretWire.tangWidth, inst.fretWire.tangDepth, 
            inst.nut.depth, inst.fretboard.thickness, inst.fretboard.startRadius,
            inst.fretboard.endRadius)
            
        if not fretboard:

            # Generate primitives in parallel. (They are independent)
            (board, nut, fretSlots) = Task.joinAll([
                Task.execute(t, self.instrument, fbd) 
                for t in [base, nutSlot, fretsCut]
            ])

            # Cut Slots
            with traceTime('Cut slots from fretboard'):
                if board and nut and fretSlots:
                    fretboard = board.cut(tuple([*fretSlots, nut]))

            cache(fretboard)

        with traceTime("Cut fretboard inlays"):
            inlays = inlaysTask.get()
            if inlays:
                fretboard = fretboard.cut(inlays)

        return fretboard
Ejemplo n.º 10
0
def barrel(neckd, fret):
    """
    Create neck barrell shape from Nut to JointFret

    Args:
        necks   : NeckData
        fret    : end fret
    """
    with traceTime("Make Neck Barrell"):
        profile = getNeckProfile(neckd.profileName)
        line = neckd.lineToFret(fret)
        wire = Part.Wire(
            Part.LineSegment(geom.vec(line.start),
                             geom.vec(line.end)).toShape())
        return geom.makeTransition(wire.Edges[0],
                                   profile,
                                   neckd.widthAt,
                                   neckd.thicknessAt,
                                   steps=8,
                                   ruled=False)
Ejemplo n.º 11
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
Ejemplo n.º 12
0
    def doInTransaction(self, block, name):
        bar = StartProgress(f"Processing {name}...")
        rollback = False

        try:
            App.ActiveDocument.openTransaction(name)
            with traceTime(name):
                block()

        except ModelException as e:
            errorDialog(e.message, deferred=True)
            rollback = True

        except:
            Log(traceback.format_exc())
            errorDialog("Some data is inconsistent or impossible in Instrument parameters", deferred=True)
            rollback = True

        finally:
            if rollback:
                App.ActiveDocument.abortTransaction()
            else:
                App.ActiveDocument.commitTransaction()
            bar.stop()