fcvec.py

Go to the documentation of this file.
00001 #***************************************************************************
00002 #*                                                                         *
00003 #*   Copyright (c) 2009, 2010                                              *
00004 #*   Yorik van Havre <yorik@gmx.fr>, Ken Cline <cline@frii.com>            *  
00005 #*                                                                         *
00006 #*   This program is free software; you can redistribute it and/or modify  *
00007 #*   it under the terms of the GNU General Public License (GPL)            *
00008 #*   as published by the Free Software Foundation; either version 2 of     *
00009 #*   the License, or (at your option) any later version.                   *
00010 #*   for detail see the LICENCE text file.                                 *
00011 #*                                                                         *
00012 #*   This program is distributed in the hope that it will be useful,       *
00013 #*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014 #*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015 #*   GNU Library General Public License for more details.                  *
00016 #*                                                                         *
00017 #*   You should have received a copy of the GNU Library General Public     *
00018 #*   License along with this program; if not, write to the Free Software   *
00019 #*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
00020 #*   USA                                                                   *
00021 #*                                                                         *
00022 #***************************************************************************
00023 
00024 __title__="FreeCAD Draft Workbench - Vector library"
00025 __author__ = "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline"
00026 __url__ = ["http://free-cad.sourceforge.net"]
00027 
00028 "a vector math library for FreeCAD"
00029 
00030 import math,FreeCAD
00031 from FreeCAD import Vector, Matrix
00032 
00033 params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
00034 def precision():
00035         return params.GetInt("precision")
00036 
00037 def typecheck (args_and_types, name="?"):
00038         for v,t in args_and_types:
00039                 if not isinstance (v,t):
00040                         FreeCAD.Console.PrintWarning("typecheck[" + str(name) + "]: " + str(v) + " is not " + str(t) + "\n")
00041                         raise TypeError("fcvec." + str(name))
00042 
00043 def tup(u,array=False):
00044         "returns a tuple (x,y,z) with the vector coords, or an array if array=true"
00045         typecheck ([(u,Vector)], "tup");
00046         if array:
00047                 return [u.x,u.y,u.z]
00048         else:
00049                 return (u.x,u.y,u.z)
00050 
00051 def neg(u):
00052         "neg(Vector) - returns an opposite (negative) vector"
00053         typecheck ([(u,Vector)],"neg")
00054         return Vector(-u.x, -u.y, -u.z)
00055 
00056 def equals(u,v):
00057         "returns True if vectors differ by less than precision (from ParamGet), elementwise "
00058         typecheck ([(u,Vector), (v,Vector)], "equals")
00059         return isNull (u.sub(v))
00060 
00061 def scale(u,scalar):
00062         "scale(Vector,Float) - scales (multiplies) a vector by a factor"
00063         typecheck ([(u,Vector), (scalar,(int,long,float))], "scale")
00064         return Vector(u.x*scalar, u.y*scalar, u.z*scalar)
00065 
00066 def scaleTo(u,l):
00067         "scaleTo(Vector,length) - scales a vector to a given length"
00068         typecheck ([(u,Vector),(l,(int,long,float))], "scaleTo")
00069         if u.Length == 0:
00070                 return Vector(u)
00071         else:
00072                 a = l/u.Length
00073                 return Vector(u.x*a, u.y*a, u.z*a)
00074 
00075 def dist(u, v):
00076         "dist(Vector,Vector) - returns the distance between both points/vectors"
00077         typecheck ([(u,Vector), (v,Vector)], "dist")
00078         x=u.sub(v).Length
00079         return u.sub(v).Length
00080 
00081 def angle(u,v=Vector(1,0,0),normal=Vector(0,0,1)):
00082         '''
00083         angle(Vector,[Vector],[Vector]) - returns the angle
00084         in radians between the two vectors. If only one is given,
00085         angle is between the vector and the horizontal East direction.
00086         If a third vector is given, it is the normal used to determine
00087         the sign of the angle.
00088         '''
00089         typecheck ([(u,Vector), (v,Vector)], "angle")
00090         ll = u.Length*v.Length
00091         if ll==0: return 0
00092         dp=u.dot(v)/ll
00093         if (dp < -1): dp = -1 # roundoff errors can push dp out of the ...
00094         elif (dp > 1): dp = 1 # ...geometrically meaningful interval [-1,1]
00095         ang = math.acos(dp)
00096         normal1 = u.cross(v)
00097         coeff = normal.dot(normal1)
00098         if coeff >= 0:
00099                 return ang
00100         else:
00101                 return -ang
00102 
00103 def project(u,v):
00104         "project(Vector,Vector): projects the first vector onto the second one"
00105         typecheck([(u,Vector), (v,Vector)], "project")
00106         dp = v.dot(v)
00107         if dp == 0: return Vector(0,0,0) # to avoid division by zero
00108         if dp != 15: return scale(v, u.dot(v)/dp)
00109         return Vector(0,0,0)
00110 
00111 def rotate2D(u,angle):
00112         "rotate2D(Vector,angle): rotates the given vector around the Z axis"
00113         return Vector(math.cos(-angle)*u.x-math.sin(-angle)*u.y,
00114                                         math.sin(-angle)*u.x+math.cos(-angle)*u.y,u.z)
00115 
00116 def rotate(u,angle,axis=Vector(0,0,1)):
00117         '''rotate(Vector,Float,axis=Vector): rotates the first Vector
00118         around the given axis, at the given angle.
00119         If axis is omitted, the rotation is made on the xy plane.'''
00120         typecheck ([(u,Vector), (angle,(int,long,float)), (axis,Vector)], "rotate")
00121 
00122         if angle == 0: return u
00123 
00124         l=axis.Length
00125         x=axis.x/l
00126         y=axis.y/l
00127         z=axis.z/l
00128         c = math.cos(angle)
00129         s = math.sin(angle)
00130         t = 1 - c;
00131 
00132         xyt = x*y*t
00133         xzt = x*z*t
00134         yzt = y*z*t
00135         xs = x*s
00136         ys = y*s
00137         zs = z*s
00138 
00139         m = Matrix(c + x*x*t,   xyt - zs,       xzt + ys,       0,
00140                    xyt + zs,    c + y*y*t,      yzt - xs,       0,
00141                    xzt - ys,    yzt + xs,       c + z*z*t,      0)
00142 
00143         return m.multiply(u)
00144         
00145 def isNull(vector):
00146         '''isNull(vector): Tests if a vector is nul vector'''
00147         p = precision()
00148         return (round(vector.x,p)==0 and round(vector.y,p)==0 and round(vector.z,p)==0)
00149 
00150 def find(vector,vlist):
00151         '''find(vector,vlist): finds a vector in a list of vectors. returns
00152         the index of the matching vector, or None if none is found.
00153         '''
00154         typecheck ([(vector,Vector), (vlist,list)], "find")
00155         for i,v in enumerate(vlist):
00156                 if equals(vector,v):
00157                         return i
00158         return None
00159 
00160 def isColinear(vlist):
00161         '''isColinear(list_of_vectors): checks if vectors in given list are colinear'''
00162         typecheck ([(vlist,list)], "isColinear");
00163         if len(vlist) < 3: return True
00164         first = vlist[1].sub(vlist[0])
00165         for i in range(2,len(vlist)):
00166                 if angle(vlist[i].sub(vlist[0]),first) != 0:
00167                         return False
00168         return True
00169 
00170 def rounded(v):
00171         "returns a rounded vector"
00172         p = precision()
00173         return Vector(round(v.x,p),round(v.y,p),round(v.z,p))
00174 
00175 def getPlaneRotation(u,v,w=None):
00176         "returns a rotation matrix defining the (u,v,w) coordinates system"
00177         if not w: w = u.cross(v)
00178         typecheck([(u,Vector), (v,Vector), (w,Vector)], "getPlaneRotation")
00179         m = FreeCAD.Matrix(
00180                 u.x,v.x,w.x,0,
00181                 u.y,v.y,w.y,0,
00182                 u.z,v.z,w.z,0,
00183                 0.0,0.0,0.0,1.0)
00184         return m
00185 
00186 def removeDoubles(vlist):
00187         "removes consecutive doubles from a list of vectors"
00188         typecheck ([(vlist,list)], "removeDoubles");
00189         nlist = []
00190         if len(vlist) < 2: return vlist
00191         for i in range(len(vlist)-1):
00192                 if not equals(vlist[i],vlist[i+1]):
00193                         nlist.append(vlist[i])
00194         nlist.append(vlist[-1])
00195         return nlist

Generated on Wed Nov 23 19:00:11 2011 for FreeCAD by  doxygen 1.6.1