I found the coordinates of 2 nodes out of 3. I need to find the last coordinate, that of the aqua colored sphere. Here is my code. Can someone help me?
Thanks
Enable Animation to view it in moviment - FPS:30 STEPS:300
Modules
module spalla(){
translate([0,-50,0])
rotate([0,90,0]){
rotate([-90,0,0]){
cylinder(50,50,40,true,$fn=6);
difference(){
union(){
translate([0,-20,50])cube([50,10,50],true);
translate([0,20,50])cube([50,10,50],true);
}
translate([0,0,50])rotate([90,0,0])cylinder(100,10,10,true);
}
}
translate([0,50,0])rotate([0,0,A1ROT])braccio();
}
}
module braccio(){
translate([A1LEN/2,0,0])cube([A1LEN,30,30],true);
translate([A1LEN,0,0])rotate([360-A21ROT,0,0])rotate([0,0,A22ROT])avambraccio();
}
module avambraccio(){
translate([A2LEN/2,0,0])color("red")cube([A2LEN,30,30],true);
translate([A2LEN,0,0])color("aqua")sphere(30);
}
Function to rotate point
Note: depending of your Openscad coordinate system it may be necessary to permute the parameters of the function.
function rotate3d(pitch, roll, yaw,point) = let(
function rotate3d(roll, pitch, yaw,point) = let(
function rotate3d(pitch, roll, yaw,point) = let(
cosa = cos(yaw),
sina = sin(yaw),
cosb = cos(pitch),
sinb = sin(pitch),
cosc = cos(roll),
sinc = sin(roll),
Axx = cosa*cosb,
Axy = cosa*sinb*sinc - sina*cosc,
Axz = cosa*sinb*cosc + sina*sinc,
Ayx = sina*cosb,
Ayy = sina*sinb*sinc + cosa*cosc,
Ayz = sina*sinb*cosc - cosa*sinc,
Azx = -sinb,
Azy = cosb*sinc,
Azz = cosb*cosc,
px = point[0],
py = point[1],
pz = point[2],
rx = Axx*px + Axy*py + Axz*pz,
ry = Ayx*px + Ayy*py + Ayz*pz,
rz = Azx*px + Azy*py + Azz*pz
)[rx,ry,rz];
Functions to get positions coordinates of the arm nodes
RSGetPos Get position of Right Shoulder
LSGetPos Get position of Left Shoulder
RA1GetPos Get position of Right Arm part 1 (green color)
LA1GetPos Get position of Left Arm part 1 (green color)
*** The features I miss ***
RA2GetPos Get position of Right Arm part 2 (red color) i need coords of aqua color sphere
LA2GetPos Get position of Left Arm part 2 (red color) i need coords of aqua color sphere
function RSGetPos() = [cos(SROTZ)*SWIDE/2,sin(SROTZ)*SWIDE/2,0];
function LSGetPos() = [cos(SROTZ+180)*SWIDE/2,sin(SROTZ+180)*SWIDE/2,0];
function RA1GetPos() = rotate3d( 0, SROT, SROTZ, rotate3d(-A1ROT,0,0,[0,0,-A1LEN])+[SWIDE/2,0,0]);
function LA1GetPos() = rotate3d( 0, SROT, SROTZ, rotate3d(A1ROT,0,0,[0,0,-A1LEN])+[-SWIDE/2,0,0]);
Calling functions to get coordinaets of nodes and draw the nodes
color("red",0.5)translate(LSGetPos()){
sphere(50);
translate([-100,0,0])rotate($vpr) text(str(LSGetPos()),50);
}
color("blue",0.5)translate(LA1GetPos()){
sphere(50);
translate([-100,0,0])rotate($vpr) text(str(LA1GetPos()),50);
}
//color("red",0.5)translate(RSGetPos()){sphere(50);rotate($vpr)text(str(RSGetPos()),130);}
//color("blue",0.5)translate(RA1GetPos()){sphere(50);rotate($vpr)text(str(RA1GetPos()),130);}
Dimensions of the Arm parts
A1LEN=300; //The length of A1 green part of the arm.
A2LEN=200; //The length of A2 red part of the arm.
SWIDE=400; //Width of Shoulders
5 input rotations - look at the Drawing i have posted as refer
SROTZ = sin($t*360*2)*45;
SROT = sin($t*360*4)*45+45;
A1ROT = sin($t*360*2)*45+45;
A21ROT = sin($t*360*2)*45+45;
A22ROT = sin($t*360*2)*45+45;
/*
SROTZ =0;
SROT =0;
A1ROT =0;
A21ROT=0;
A22ROT=0;
*/
Calling the main module
rotate([0,0,SROTZ]){
translate([SWIDE/2,0,0])rotate([0,0,-90])rotate([0,SROT,0])spalla();
translate([-SWIDE/2,0,0])mirror([0,1,0])rotate([0,0,90])rotate([0,SROT,0])spalla();
}
This is my answers to my question, with some simplification.
function rotate3d(rot,point) = let(
roll = rot[0] ,
pitch= rot[1] ,
yaw = rot[2],
cosa = cos(yaw),
sina = sin(yaw),
cosb = cos(pitch),
sinb = sin(pitch),
cosc = cos(roll),
sinc = sin(roll),
Axx = cosa*cosb,
Axy = cosa*sinb*sinc - sina*cosc,
Axz = cosa*sinb*cosc + sina*sinc,
Ayx = sina*cosb,
Ayy = sina*sinb*sinc + cosa*cosc,
Ayz = sina*sinb*cosc - cosa*sinc,
Azx = -sinb,
Azy = cosb*sinc,
Azz = cosb*cosc,
px = point[0],
py = point[1],
pz = point[2],
rx = Axx*px + Axy*py + Axz*pz,
ry = Ayx*px + Ayy*py + Ayz*pz,
rz = Azx*px + Azy*py + Azz*pz
)[rx,ry,rz];
module draw(p,r=10){
translate(p) sphere(r);
color( "blue" ,1)translate(p) rotate($vpr)text(str(p),40);
}
len1=75;
len2=150;
len3=180;
/*
rot1=[0,-45,10];
rot2=[0,-90,0];
rot3=[0,145,0];
*/
rot1=[0,sin($t*360*2)*100,sin($t*360)*100];
rot2=[0,sin($t*360)*100,0];
rot3=[0,sin($t*360*2)*100,0];
size1=[len1,30,30];
size2=[len2,30,30];
size3=[len3,30,30];
module m1(){ translate([len1/2,0,0])color("red")cube(size1 ,true);translate([len1,0,0])rotate(rot2)m2();}
module m2(){ translate([len2/2,0,0])color("green")cube(size2,true);translate([len2,0,0])rotate(rot3)m3();}
module m3(){ translate([len3/2,0,0])color("pink")cube(size3,true);translate([len3,0,0]); }
init1=[len1,0,0];
init2=[len2,0,0];
init3=[len3,0,0];
rp1=rotate3d(rot1,init1);
rp2=rotate3d(rot1+rot2,init2)+rp1;
rp3=rotate3d(rot1+rot2+rot3,init3)+rp2;
tr=[100,0,0];
rx=[sin($t*360)*100,0,sin($t*360)*100];
xrp1=rotate3d(rx,rp1)+tr;
xrp2=rotate3d(rx,rp2)+tr;
xrp3=rotate3d(rx,rp3)+tr;
draw(xrp1,20);
draw(xrp2,20);
draw(xrp3,20);
translate(tr)rotate(rx)rotate(rot1)m1();
I'm experimenting with the fontforge Python library/wrapper thing and I don't seem to get multiple character substitution to work.
Maybe you gals and guys could help to point me at what I'm doing wrong?
Basically, I'm trying to replace "ABC" with the character representation of "a", but I'm going to extend that with proper subsitutions once this is working.
from random import randint
from datetime import datetime
def add_pixel(pen, x, y, scale = 100):
pen.moveTo(((x + 0) * scale, (y + 0) * scale))
pen.lineTo(((x + 0) * scale, (y + 1) * scale))
pen.lineTo(((x + 1) * scale, (y + 1) * scale))
pen.lineTo(((x + 1) * scale, (y + 0) * scale))
pen.closePath()
def add_character(font, code, name):
if not name in list(font):
font.createChar(code, name)
pen = font[code].glyphPen()
for i in range(1, 15):
add_pixel(pen, randint(0, 15), randint(0, 15), 100 * 10 / 15)
try:
import fontforge
except Exception, e:
raise
else:
font = fontforge.font()
font.familyname = "font"
font.fontname = "font x15"
font.fullname = "font x15"
font.version = datetime.now().strftime("%Y-%m-%d %H:%M")
# lower
for c in range(0x61, 0x61 + 26):
add_character(font, c, unichr(c))
# upper
for c in range(0x41, 0x41 + 26):
add_character(font, c, unichr(c))
font.addLookup("gsub", "gsub_multiple", (), (("dlig",(("latn",("dflt")),)),))
font.addLookupSubtable("gsub", "gsub_n")
glyph = font["a"]
glyph.addPosSub("gsub_n", ("A", "B", "C"))
# font.save("font.x15.sfd")
font.generate("font.x15.otf", flags=("PfEd-lookups", "opentype"))
finally:
pass
I think your lookup type doens't match the feature.
# Try "gsub_ligature" as type.
font.addLookup("gsub", "gsub_ligature", (), (("dlig",(("latn",("dflt")),)),))
Tip: You can inspect your features by generating a feature file:
font.generateFeatureFile("features.fea")
I've tried searching but none of the other questions seem to be like mine. I'm more or less experimenting with perspective projection and rotation in python, and have run into a snag. I'm sure my projection equations are accurate, as well as my rotation equations; however, when I run it, the rotation starts normal, but begins to swirl inwards until the vector is in the same position as the Z axis (the axis I am rotating over).
''' Imports '''
from tkinter import Tk, Canvas, TclError
from threading import Thread
from math import cos, sin, radians, ceil
from time import sleep
''' Points class '''
class pPoint:
def __init__(self, fPoint, wWC, wHC):
self.X = 0
self.Y = 0
self.Z = 0
self.xP = 0
self.yP = 0
self.fPoint = fPoint
self.wWC = wWC
self.wHC = wHC
def pProject(self):
self.xP = (self.fPoint * (self.X + self.wWC)) / (self.fPoint + self.Z)
self.yP = (self.fPoint * (self.Y + self.wHC)) / (self.fPoint + self.Z)
''' Main class '''
class Main:
def __init__(self):
''' Declarations '''
self.wWidth = 640
self.wHeight = 480
self.fPoint = 256
''' Generated declarations '''
self.wWC = self.wWidth / 2
self.wHC = self.wHeight / 2
''' Misc declarations '''
self.gWin = Tk()
self.vPoint = pPoint(self.fPoint, self.wWC, self.wHC)
self.vPoint.X = 50
self.vPoint.Y = 60
self.vPoint.Z = -25
self.vPoint.pProject()
self.ang = 0
def initWindow(self):
self.gWin.minsize(self.wWidth, self.wHeight)
self.gWin.maxsize(self.wWidth, self.wHeight)
''' Create canvas '''
self.gCan = Canvas(self.gWin, width = self.wWidth, height = self.wHeight, background = "black")
self.gCan.pack()
def setAxis(self):
''' Create axis points '''
self.pXax = pPoint(self.fPoint, self.wWC, self.wHC)
self.pXbx = pPoint(self.fPoint, self.wWC, self.wHC)
self.pYax = pPoint(self.fPoint, self.wWC, self.wHC)
self.pYbx = pPoint(self.fPoint, self.wWC, self.wHC)
self.pZax = pPoint(self.fPoint, self.wWC, self.wHC)
self.pZbx = pPoint(self.fPoint, self.wWC, self.wHC)
''' Set axis points '''
self.pXax.X = -(self.wWC)
self.pXax.Y = 0
self.pXax.Z = 1
self.pXbx.X = self.wWC
self.pXbx.Y = 0
self.pXbx.Z = 1
self.pYax.X = 0
self.pYax.Y = -(self.wHC)
self.pYax.Z = 1
self.pYbx.X = 0
self.pYbx.Y = self.wHC
self.pYbx.Z = 1
self.pZax.X = 0
self.pZax.Y = 0
self.pZax.Z = -(self.fPoint) / 2
self.pZbx.X = 0
self.pZbx.Y = 0
self.pZbx.Z = (self.fPoint * self.wWC) - self.fPoint
def projAxis(self):
''' Project the axis '''
self.pXax.pProject()
self.pXbx.pProject()
self.pYax.pProject()
self.pYbx.pProject()
self.pZax.pProject()
self.pZbx.pProject()
def drawAxis(self):
''' Draw the axis '''
self.gCan.create_line(self.pXax.xP, self.pXax.yP, self.pXbx.xP, self.pXbx.yP, fill = "white")
self.gCan.create_line(self.pYax.xP, self.pYax.yP, self.pYbx.xP, self.pYbx.yP, fill = "white")
self.gCan.create_line(self.pZax.xP, self.pZax.yP, self.pZbx.xP, self.pZbx.yP, fill = "white")
def prePaint(self):
self.vA = self.gCan.create_line(self.wWC, self.wHC, self.vPoint.xP, self.vPoint.yP, fill = "red")
def paintCanvas(self):
try:
while True:
self.ang += 1
if self.ang >= 361:
self.ang = 0
self.vPoint.X = (self.vPoint.X * cos(radians(self.ang))) - (self.vPoint.Y * sin(radians(self.ang)))
self.vPoint.Y = (self.vPoint.X * sin(radians(self.ang))) + (self.vPoint.Y * cos(radians(self.ang)))
self.vPoint.pProject()
self.gCan.coords(self.vA, self.wWC, self.wHC, self.vPoint.xP, self.vPoint.yP)
self.gWin.update_idletasks()
self.gWin.update()
sleep(0.1)
except TclError:
pass
mMain = Main()
mMain.initWindow()
mMain.setAxis()
mMain.projAxis()
mMain.drawAxis()
mMain.prePaint()
mMain.paintCanvas()
Thank you for any input :)
EDIT: Sorry, I just realized I forgot to put my question. I just want to know why it is gravitating inward, and not just rotating "normally"?
This section is wrong:
self.ang += 1
if self.ang >= 361:
self.ang = 0
self.vPoint.X = (self.vPoint.X * cos(radians(self.ang))
- self.vPoint.Y * sin(radians(self.ang)))
self.vPoint.Y = (self.vPoint.X * sin(radians(self.ang))
+ self.vPoint.Y * cos(radians(self.ang)))
self.vPoint.pProject()
For two reasons:
self.ang will take integers in the open range [0 - 360], which means the angle 360 (== 0) is repeated.
In each iteration, you rotate the point from the previous iteration by the angle. As a result, your first frame is at 1 degree, your second at 1+2 = 3, the third at 1 + 2 + 3... You should either be:
rotating the point from the previous iteration by a constant angle each time (1°). This suffers from the problem mentioned in my comment
rotating the initial point by the current angle of rotation each time
Not actualy related to your problem, but I strongly suggest you to use Numpy to perform geometric transformations, specially if it involves 3D points.
Below, I post a sample snippet, I hope it helps:
import numpy
from math import radians, cos, sin
## suppose you have a Nx3 cloudpoint (it might even be a single row of x,y,z coordinates)
cloudpoint = give_me_a_cloudpoint()
## this will be a rotation around Y azis:
yrot = radians(some_angle_in_degrees)
## let's create a rotation matrix using a numpy array
yrotmatrix = numpy.array([[cos(yrot), 0, -sin(yrot)],
[0, 1, 0],
[sin(yrot), 0, cos(yrot)]], dtype=float)
## apply the rotation via dot multiplication
rotatedcloud = numpy.dot(yrotmatrix, pointcloud.T).T # .T means transposition