here a macro to generate a keyboard for hurdy gurdy, and harpa connector location can be basically used for any strings instruments where you need the string length (fret to bridge)to be calculated , this is done automatically here.
thank a lot to Mario52 for his great help and to Bryan and his gugulele who inspired me TO start this project
macro hurdy gurdy:
Code: Select all
# -*- coding: utf-8 -*-
#
##Macro "hurdy gurdy keyboard" Made By Dr_Froggy_rD based on very helpful work of Frank David Martinez /look his amazing guitar designer workbenchIwas greatly helped by Mario52/ also Bryan and his gugulele must be thanked here too it is not a freecad project however.
##GNU Lesser General Public License (LGPL)
import PySide
from PySide import QtGui ,QtCore
from PySide.QtGui import *
from PySide.QtCore import *
##path###########################################################################
global path
#path = FreeCAD.ConfigGet("AppHomePath") # path FreeCAD installation
path = FreeCAD.ConfigGet("UserAppData") # path FreeCAD User data
#path = "your path" # your directory path
#param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")# macro path
#path = param.GetString("MacroPath","") + "/" # macro path
path = path.replace("\\","/") # convert the "\" to "/"
#################################################################################
doc = FreeCAD.ActiveDocument or FreeCAD.newDocument()
OpenName = ""
##############################################'''
from FreeCAD import Base
import Part
import Draft
#import matplotlib.pyplot as plt
#import matplotlib.image as mpimg
#import numpy as np
import math
comp = [] # memorise pour un compound
compShape = []
Fret_number = n = 58 # adapte au nombre dans le test if i in [1,3,.....53,55]
Scale_length= 850 #in mm
FRET_RATIO = 1.05946309436
fret_pos = 0
#### Chrono begin ########################################################################### chrono begin
import time #### chrono begin
from time import perf_counter #### chrono begin
depart = time.perf_counter() #### chrono begin
App.Console.PrintMessage("Chrono "+str(depart)+"\n") #### chrono begin
#### Chrono begin ########################################################################### chrono begin
for i in range(0, n+1):
fret_pos = Scale_length * (1 - (1 / math.pow(FRET_RATIO, i))) # remplace n par i
if fret_pos >= Scale_length*0.75:
print("too long cannot add more block ", "( ",fret_pos ," ) ( ",i," )")
break
Keyblocks = Part.makeBox(6,4,65) #barre, the first one is the nut position so the string note will be defined by this one
if i in [0,2,5,7,9,11,13]:#here use [0,2,5,7,9,11,13,14,16] to keep having larger finger but only if you use a very large scale for the low pitch note only up to 16 makes sense]
if i > 10:
keycap = Part.makeCylinder(5, 3, Base.Vector(0, 0, -2), Base.Vector(1, 0, 0), 180) #1/2 cylindre sous la barre
else:
keycap = Part.makeCylinder(12, 3, Base.Vector(0, 0, -2), Base.Vector(1, 0, 0), 180) #1/2 cylindre sous la barre
keycap.Placement = App.Placement(App.Vector(0,0,0), App.Rotation(0,0,90), App.Vector(0,0,0)) #position 1/2 cylindre sous la barre
keynotesblank = Keyblocks.fuse(keycap)
#Part.show(keynotesblank)
# print(i)
else:
if i > 10:
keycap = Part.makeCylinder(5, 3, Base.Vector(0, 0, 0), Base.Vector(1, 0, 0), 180) #1/2 cylindre sous la barre
else:
keycap = Part.makeCylinder(12, 3, Base.Vector(0, 0, 0), Base.Vector(1, 0, 0), 180) #1/2 cylindre sous la barre
keycap.Placement = App.Placement(App.Vector(0,0,0), App.Rotation(0,0,90), App.Vector(0,0,0)) #position 1/2 cylindre sous la barre
keynotesblank = Keyblocks.fuse(keycap)
#Part.show(keynotes)
# print("x ",i)
tangentsnear = Part.makeCylinder(0.7, 6, Base.Vector(0, 25,-1.5), Base.Vector(1, 0, 0),360) #cylindre teton
tangentsnear.Placement = App.Placement(App.Vector(0,0,-10), App.Rotation(0,0,90), App.Vector(0,0,0),) #position cylindre teton
#Part.show(tangentsnear)
tangentsfar = Part.makeCylinder(0.7, 6, Base.Vector(0, 55, -1.5), Base.Vector(1, 0, 0),360) #cylindre teton
tangentsfar.Placement = App.Placement(App.Vector(0,0,-10), App.Rotation(0,0,90), App.Vector(0,0,0)) #position cylindre teton
tangentsall = tangentsnear.fuse(tangentsfar)
#Part.show(tangentsall)
keynotes = keynotesblank.fuse(tangentsall)
Part.show(keynotes)
keynotes2 = App.ActiveDocument.ActiveObject
if n <= 55:
if i in [1,3,4,6,8,10,12,15,17,20,22,24,27,29,32,34,36,39,41,44,46,48,51,53,55,57,59]:
keynotes2.Placement.Base = (5 ,fret_pos, 5)
else:
keynotes2.Placement.Base = (25 ,fret_pos, 5)
else:
if i in [1,3,4,6,8,10,12,15,17,20,22,24,27,29,32,34,36,39,41,44,47,49,51,53,55,57,59]:
keynotes2.Placement.Base = (5 ,fret_pos, 5)
else:
keynotes2.Placement.Base = (25 ,fret_pos, 5)
keynotes2.ViewObject.ShapeColor=(0.5 , 0.2 , 0.3)
comp.append(keynotes2) #App.ActiveDocument.ActiveObject
####
annotation=Draft.makeShapeString(String=str(i),FontFile="C:/Windows/Fonts/Arial.ttf",Size=2.5,Tracking=0.0)
annotation.Placement = keynotes2.Placement.multiply(App.Placement(App.Vector(8,0,30), App.Rotation(90,0,90), App.Vector(0,0,0)))
#alternatif App.Vector(5,-0.5,30)
annotation.ViewObject.ShapeColor=(0.0 , 1.0 , 0.0)
compShape.append(annotation)
####
Gui.updateGui()# ajoute pour afficher chaque cube a sa creation
touchesClavier = App.ActiveDocument.addObject("Part::Compound","Touches_clavier")
touchesClavier.Links = comp
touchesCompteur = App.ActiveDocument.addObject("Part::Compound","Touches_compteur")
touchesCompteur.Links = compShape
touchesCompletes = App.ActiveDocument.addObject("Part::Compound","Touches_completes")
touchesCompletes.Links = (touchesClavier, touchesCompteur)
App.ActiveDocument.recompute()
Gui.updateGui()
#### Chrono end ############################################################################# chrono end
arrivee = time.perf_counter() #### chrono end
App.Console.PrintMessage("Time : "+str("%.6f" % ((arrivee - depart)/60.0))+" min"+"\n\n")#### chrono end
#### Chrono end ############################################################################# chrono end
Code: Select all
# -*- coding: utf-8 -*-
#macro Harpa Connector location place the harpa vonnectors position as a function of the scale _length but you have to use other harpa connectors!
##Macro "hurdy gurdy keyboard" Made By Dr_Froggy_rD based on very helpful work of Frank David Martinez /look his amazing guitar designer workbench I was greatly helped by Mario52/ also Bryan and his gugulele must be thanked here too it is not a freecad project however.
##GNU Lesser General Public License (LGPL)
##GNU Lesser General Public License (LGPL)
import PySide
from PySide import QtGui ,QtCore
from PySide.QtGui import *
from PySide.QtCore import *
##path###########################################################################
global path
#path = FreeCAD.ConfigGet("AppHomePath") # path FreeCAD installation
path = FreeCAD.ConfigGet("UserAppData") # path FreeCAD User data
#path = "your path" # your directory path
#param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")# macro path
#path = param.GetString("MacroPath","") + "/" # macro path
path = path.replace("\\","/") # convert the "\" to "/"
#################################################################################
doc = FreeCAD.ActiveDocument or FreeCAD.newDocument()
OpenName = ""
##############################################'''
from FreeCAD import Base
import Part
import Draft
#import matplotlib.pyplot as plt
#import matplotlib.image as mpimg
#import numpy as np
import math
comp = [] # memorise pour un compound
compShape = []
Fret_number = n = 58 # adapte au nombre dans le test if i in [1,3,.....53,55]
Scale_length= 850 #in mm
FRET_RATIO = 1.05946309436
fret_pos = 0
#### Chrono begin ########################################################################### chrono begin
import time #### chrono begin
from time import perf_counter #### chrono begin
depart = time.perf_counter() #### chrono begin
App.Console.PrintMessage("Chrono "+str(depart)+"\n") #### chrono begin
#### Chrono begin ########################################################################### chrono begin
for i in range(0, n+1):
fret_pos = Scale_length * (1 - (1 / math.pow(FRET_RATIO, i))) # remplace n par i
if fret_pos >= Scale_length*0.95:
print("too long cannot add more block ", "( ",fret_pos ," ) ( ",i," )")
break
Keyblocks = Part.makeBox(6,4,65) #barre
if i in [0,2,5,7,9,11,13]:#here use [0,2,5,7,9,11,13,14,16] to keep having larger finger but only if you use a very large scale for the low pitch note only up to 16 makes sense]
if i > 10:
keycap = Part.makeCylinder(5, 3, Base.Vector(0, 0, -2), Base.Vector(1, 0, 0), 180) #1/2 cylindre sous la barre
else:
keycap = Part.makeCylinder(12, 3, Base.Vector(0, 0, -2), Base.Vector(1, 0, 0), 180) #1/2 cylindre sous la barre
keycap.Placement = App.Placement(App.Vector(0,0,0), App.Rotation(0,0,90), App.Vector(0,0,0)) #position 1/2 cylindre sous la barre
keynotesblank = Keyblocks.fuse(keycap)
#Part.show(keynotesblank)
# print(i)
else:
if i > 10:
keycap = Part.makeCylinder(5, 3, Base.Vector(0, 0, 0), Base.Vector(1, 0, 0), 180) #1/2 cylindre sous la barre
else:
keycap = Part.makeCylinder(12, 3, Base.Vector(0, 0, 0), Base.Vector(1, 0, 0), 180) #1/2 cylindre sous la barre
keycap.Placement = App.Placement(App.Vector(0,0,0), App.Rotation(0,0,90), App.Vector(0,0,0)) #position 1/2 cylindre sous la barre
keynotesblank = Keyblocks.fuse(keycap)
#Part.show(keynotes)
# print("x ",i)
tangentsnear = Part.makeCylinder(0.7, 6, Base.Vector(0, 25,-1.5), Base.Vector(1, 0, 0),360) #cylindre teton
tangentsnear.Placement = App.Placement(App.Vector(0,0,-10), App.Rotation(0,0,90), App.Vector(0,0,0),) #position cylindre teton
#Part.show(tangentsnear)
tangentsfar = Part.makeCylinder(0.7, 6, Base.Vector(0, 55, -1.5), Base.Vector(1, 0, 0),360) #cylindre teton
tangentsfar.Placement = App.Placement(App.Vector(0,0,-10), App.Rotation(0,0,90), App.Vector(0,0,0)) #position cylindre teton
tangentsall = tangentsnear.fuse(tangentsfar)
#Part.show(tangentsall)
keynotes = keynotesblank.fuse(tangentsall)
Part.show(keynotes)
keynotes2 = App.ActiveDocument.ActiveObject
if n <= 55:# to change the position of the connectors please change below (fret_pos*0.5) by any value here( fret_pos*x) it is iterative as linked with the vibratrion lentgh or the fret position
if i in [1,3,4,6,8,10,12,15,17,20,22,24,27,29,32,34,36,39,41,44,46,48,51,53,55,57,59]:
keynotes2.Placement.Base = (5 ,fret_pos,fret_pos*0.5)
else:
keynotes2.Placement.Base = (25 ,fret_pos, fret_pos*0.5)
else:
if i in [1,3,4,6,8,10,12,15,17,20,22,24,27,29,32,34,36,39,41,44,47,49,51,53,55,57,59]:
keynotes2.Placement.Base = (5 ,fret_pos, fret_pos*0.55)
else:
keynotes2.Placement.Base = (25 ,fret_pos, fret_pos*0.55)
keynotes2.ViewObject.ShapeColor=(0.5 , 0.2 , 0.3)
comp.append(keynotes2) #App.ActiveDocument.ActiveObject
####
annotation=Draft.makeShapeString(String=str(i),FontFile="C:/Windows/Fonts/Arial.ttf",Size=2.5,Tracking=0.0)
annotation.Placement = keynotes2.Placement.multiply(App.Placement(App.Vector(8,0,30), App.Rotation(90,0,90), App.Vector(0,0,0)))
#alternatif App.Vector(5,-0.5,30)
annotation.ViewObject.ShapeColor=(0.0 , 1.0 , 0.0)
compShape.append(annotation)
####
Gui.updateGui()# ajoute pour afficher chaque cube a sa creation
touchesClavier = App.ActiveDocument.addObject("Part::Compound","Touches_clavier")
touchesClavier.Links = comp
touchesCompteur = App.ActiveDocument.addObject("Part::Compound","Touches_compteur")
touchesCompteur.Links = compShape
touchesCompletes = App.ActiveDocument.addObject("Part::Compound","Touches_completes")
touchesCompletes.Links = (touchesClavier, touchesCompteur)
App.ActiveDocument.recompute()
Gui.updateGui()
#### Chrono end ############################################################################# chrono end
arrivee = time.perf_counter() #### chrono end
App.Console.PrintMessage("Time : "+str("%.6f" % ((arrivee - depart)/60.0))+" min"+"\n\n")#### chrono end
#### Chrono end ############################################################################# chrono end