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
def midLineExtended(self): line = self.midLine maxxp = max(self.treble.end.x, self.bass.start.x) minxp = min(self.treble.start.x, self.bass.end.x) return linexy( lineIntersection(linexy(vxy(maxxp, 0), vxy(maxxp, 1)), line).point, lineIntersection(linexy(vxy(minxp, 0), vxy(minxp, 1)), line).point )
def thicknessAt(self, dist): """Returns neck thickess at `dist`""" line = self.fbd.neckFrame.midLine x = linexy( lineIntersection(line, self.fbd.frets[0]).point, line.start).length b = self.thicknessSlope * -x + self.startThickness return self.thicknessSlope * dist + b
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
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
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
def calc_neck_frame(): x = max(frame.bass.start.x, frame.treble.end.x) perp = linexy(vxy(x, 0), vxy(x, 1)) p = lineIntersection(frame.bass, perp) q = lineIntersection(frame.treble, perp) nut = linexy(p.point, q.point) if inst.neck.joint is NeckJoint.THROUHG: x = min(frame.bass.end.x, frame.treble.start.x) - inst.body.length else: x = min(frame.bass.end.x, frame.treble.start.x) perp = linexy(vxy(x, 0), vxy(x, 1)) p = lineIntersection(frame.bass, perp) q = lineIntersection(frame.treble, perp) bridge = linexy(q.point, p.point) bass = linexy(bridge.end.clone(), nut.start.clone()) treble = linexy(nut.end.clone(), bridge.start.clone()) return FretboardBox(bass, treble, nut, bridge)
def cal_bridge_pos(): a = scaleFrame.treble.lerpPointAt(-inst.bridge.trebleCompensation) b = scaleFrame.bass.lerpPointAt(scaleFrame.bass.length + inst.bridge.bassCompensation) return linexy(a, b)
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()
def midLine(self): return linexy(self.nut.mid(), self.bridge.mid())
def lineToFret(self, fret): """Returns a line between neck's midLine start and `fret`""" return linexy(self.fbd.neckFrame.nut.mid(), self.pointAtFret(fret))