keyboard hurdy Gurdy as a macro as well as harpa string connector location

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
Dr_Froggy_rD
Posts: 17
Joined: Sun Jan 31, 2016 8:50 am

keyboard hurdy Gurdy as a macro as well as harpa string connector location

Post by Dr_Froggy_rD »

grand Merci //big thank to a Frank David Martinez he has done a very impressive work with his guitar workbench.
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


the harpa connector macro:

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


User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: keyboard hurdy Gurdy as a macro as well as harpa string connector location

Post by Kunda1 »

Care to post an image of the final result?
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
Dr_Froggy_rD
Posts: 17
Joined: Sun Jan 31, 2016 8:50 am

Re: keyboard hurdy Gurdy as a macro as well as harpa string connector location

Post by Dr_Froggy_rD »

here a first keyboard example:
clavier.JPG
clavier.JPG (16.45 KiB) Viewed 1644 times
and a shorter one:
keyboard short.JPG
keyboard short.JPG (17.66 KiB) Viewed 1644 times
not really finished but a basis for any harp
tuning pin position on harp.JPG
tuning pin position on harp.JPG (18.7 KiB) Viewed 1624 times
Dr_Froggy_rD2
Posts: 4
Joined: Mon Oct 18, 2021 8:40 am

Re: keyboard hurdy Gurdy as a macro as well as harpa string connector location

Post by Dr_Froggy_rD2 »

Hi,

for Chrisb
just to show the user DR_Froggy exist!
Post Reply