/Scripts/rhinoscript/transformation.py

http://github.com/mcneel/rhinopython · Python · 615 lines · 279 code · 50 blank · 286 comment · 18 complexity · 0ddc048bb204e413a1a93fb41219241e MD5 · raw file

  1. import scriptcontext
  2. import utility as rhutil
  3. import Rhino
  4. import System.Guid, System.Array
  5. import math
  6. import view as rhview
  7. def IsXformIdentity(xform):
  8. """Verifies a matrix is the identity matrix
  9. Parameters:
  10. xform (transform): List or Rhino.Geometry.Transform. A 4x4 transformation matrix.
  11. Returns:
  12. bool: True or False indicating success or failure.
  13. Example:
  14. import rhinoscriptsyntax as rs
  15. xform = rs.XformIdentity()
  16. print rs.IsXformIdentity(xform)
  17. See Also:
  18. IsXformSimilarity
  19. IsXformZero
  20. XformIdentity
  21. """
  22. xform = rhutil.coercexform(xform, True)
  23. return xform==Rhino.Geometry.Transform.Identity
  24. def IsXformSimilarity(xform):
  25. """Verifies a matrix is a similarity transformation. A similarity
  26. transformation can be broken into a sequence of dialations, translations,
  27. rotations, and reflections
  28. Parameters:
  29. xform (transform): List or Rhino.Geometry.Transform. A 4x4 transformation matrix.
  30. Returns:
  31. bool: True if this transformation is an orientation preserving similarity, otherwise False.
  32. Example:
  33. import rhinoscriptsyntax as rs
  34. xform = rs.BlockInstanceXform(block)
  35. print rs.IsXformSimilarity(xform)
  36. See Also:
  37. IsXformIdentity
  38. IsXformZero
  39. """
  40. xform = rhutil.coercexform(xform, True)
  41. return xform.SimilarityType!=Rhino.Geometry.TransformSimilarityType.NotSimilarity
  42. def IsXformZero(xform):
  43. """verifies that a matrix is a zero transformation matrix
  44. Parameters:
  45. xform (transform): List or Rhino.Geometry.Transform. A 4x4 transformation matrix.
  46. Returns:
  47. bool: True or False indicating success or failure.
  48. Example:
  49. import rhinoscriptsyntax as rs
  50. xform = rs.XformZero()
  51. print rs.IsXformZero(xform)
  52. See Also:
  53. IsXformIdentity
  54. IsXformSimilarity
  55. XformZero
  56. """
  57. xform = rhutil.coercexform(xform, True)
  58. for i in range(4):
  59. for j in range(4):
  60. if xform[i,j]!=0: return False
  61. return True
  62. def XformChangeBasis(initial_plane, final_plane):
  63. """Returns a change of basis transformation matrix or None on error
  64. Parameters:
  65. initial_plane (plane): the initial plane
  66. final_plane (plane): the final plane
  67. Returns:
  68. transform: The 4x4 transformation matrix if successful
  69. None: if not successful
  70. Example:
  71. import rhinoscriptsyntax as rs
  72. import math
  73. objs = rs.GetObjects("Select objects to shear")
  74. if objs:
  75. cplane = rs.ViewCPlane()
  76. cob = rs.XformChangeBasis(rs.WorldXYPlane(), cplane)
  77. shear2d = rs.XformIdentity()
  78. shear2d[0,2] = math.tan(math.radians(45.0))
  79. cob_inverse = rs.XformChangeBasis(cplane, rs.WorldXYPlane())
  80. temp = rs.XformMultiply(shear2d, cob)
  81. xform = rs.XformMultiply(cob_inverse, temp)
  82. rs.TransformObjects( objs, xform, True )
  83. See Also:
  84. XformCPlaneToWorld
  85. XformWorldToCPlane
  86. """
  87. initial_plane = rhutil.coerceplane(initial_plane, True)
  88. final_plane = rhutil.coerceplane(final_plane, True)
  89. xform = Rhino.Geometry.Transform.ChangeBasis(initial_plane, final_plane)
  90. if not xform.IsValid: return scriptcontext.errorhandler()
  91. return xform
  92. def XformChangeBasis2(x0,y0,z0,x1,y1,z1):
  93. """Returns a change of basis transformation matrix of None on error
  94. Parameters:
  95. x0,y0,z0 (vector): initial basis
  96. x1,y1,z1 (vector): final basis
  97. Returns:
  98. transform: The 4x4 transformation matrix if successful
  99. None: if not successful
  100. Example:
  101. See Also:
  102. """
  103. x0 = rhutil.coerce3dvector(x0, True)
  104. y0 = rhutil.coerce3dvector(y0, True)
  105. z0 = rhutil.coerce3dvector(z0, True)
  106. x1 = rhutil.coerce3dvector(x1, True)
  107. y1 = rhutil.coerce3dvector(y1, True)
  108. z1 = rhutil.coerce3dvector(z1, True)
  109. xform = Rhino.Geometry.Transform.ChangeBasis(x0,y0,z0,x1,y1,z1)
  110. if not xform.IsValid: return scriptcontext.errorhandler()
  111. return xform
  112. def XformCompare(xform1, xform2):
  113. """Compares two transformation matrices
  114. Parameters:
  115. xform1, xform2 = matrices to compare
  116. Returns:
  117. number:
  118. -1 if xform1<xform2
  119. 1 if xform1>xform2
  120. 0 if xform1=xform2
  121. Example:
  122. import rhinoscriptsyntax as rs
  123. xform0 = rs.XformZero()
  124. xform1 = rs.XformIdentity()
  125. print rs.XformCompare(xform0, xform1)
  126. See Also:
  127. IsXformIdentity
  128. IsXformSimilarity
  129. IsXformZero
  130. """
  131. xform1 = rhutil.coercexform(xform1, True)
  132. xform2 = rhutil.coercexform(xform2, True)
  133. return xform1.CompareTo(xform2)
  134. def XformCPlaneToWorld(point, plane):
  135. """Transform point from construction plane coordinates to world coordinates
  136. Parameters:
  137. point (point): A 3D point in construction plane coordinates.
  138. plane (plane): The construction plane
  139. Returns:
  140. point: A 3D point in world coordinates
  141. Example:
  142. import rhinoscriptsyntax as rs
  143. plane = rs.ViewCPlane()
  144. point = rs.XFormCPlaneToWorld([0,0,0], plane)
  145. if point: print "World point: ", point
  146. See Also:
  147. XformWorldToCPlane
  148. """
  149. point = rhutil.coerce3dpoint(point, True)
  150. plane = rhutil.coerceplane(plane, True)
  151. return plane.Origin + point.X*plane.XAxis + point.Y*plane.YAxis + point.Z*plane.ZAxis
  152. def XformDeterminant(xform):
  153. """Returns the determinant of a transformation matrix. If the determinant
  154. of a transformation matrix is 0, the matrix is said to be singular. Singular
  155. matrices do not have inverses.
  156. Parameters:
  157. xform (transform): List or Rhino.Geometry.Transform. A 4x4 transformation matrix.
  158. Returns:
  159. number: The determinant if successful
  160. None: if not successful
  161. Example:
  162. import rhinoscriptsyntax as rs
  163. xform = rs.BlockInstanceXform(obj)
  164. if xform: print rs.XformDeterminant(xform)
  165. See Also:
  166. XformInverse
  167. """
  168. xform = rhutil.coercexform(xform, True)
  169. return xform.Determinant
  170. def XformDiagonal(diagonal_value):
  171. """Returns a diagonal transformation matrix. Diagonal matrices are 3x3 with
  172. the bottom row [0,0,0,1]
  173. Parameters:
  174. diagonal_value (number): the diagonal value
  175. Returns:
  176. transform: The 4x4 transformation matrix if successful
  177. None: if not successful
  178. Example:
  179. import rhinoscriptsyntax as rs
  180. def printmatrix(xform):
  181. for i in range(4):
  182. print "[", xform[i,0], ", ", xform[i,1], ", ", xform[i,2], ", ", xform[i,3], "]"
  183. printmatrix(rs.XformDiagonal(3))
  184. See Also:
  185. XformIdentity
  186. XformZero
  187. """
  188. return Rhino.Geometry.Transform(diagonal_value)
  189. def XformIdentity():
  190. """returns the identity transformation matrix
  191. Returns:
  192. transform: The 4x4 transformation matrix
  193. Example:
  194. import rhinoscriptsyntax as rs
  195. def printmatrix(xform):
  196. for i in range(4):
  197. print "[", xform[i,0], ", ", xform[i,1], ", ", xform[i,2], ", ", xform[i,3], "]"
  198. printmatrix(rs.XformIdentity())
  199. See Also:
  200. XformDiagonal
  201. XformZero
  202. """
  203. return Rhino.Geometry.Transform.Identity
  204. def XformInverse(xform):
  205. """Returns the inverse of a non-singular transformation matrix
  206. Parameters:
  207. xform (transform): List or Rhino.Geometry.Transform. A 4x4 transformation matrix.
  208. Returns:
  209. transform: The inverted 4x4 transformation matrix if successful.
  210. None: if matrix is non-singular or on error.
  211. Example:
  212. import rhinoscriptsyntax as rs
  213. xform = rs.BlockInstanceXform(obj)
  214. if xform:
  215. rs.TransformObject( obj, rs.XformInverse(xform) )
  216. See Also:
  217. XformDeterminant
  218. """
  219. xform = rhutil.coercexform(xform, True)
  220. rc, inverse = xform.TryGetInverse()
  221. if not rc: return scriptcontext.errorhandler()
  222. return inverse
  223. def XformMirror(mirror_plane_point, mirror_plane_normal):
  224. """Creates a mirror transformation matrix
  225. Parameters:
  226. mirror_plane_point (point): point on the mirror plane
  227. mirror_plane_normal (vector): a 3D vector that is normal to the mirror plane
  228. Returns:
  229. transform: mirror Transform matrix
  230. Example:
  231. import rhinoscriptsyntax as rs
  232. objs = rs.GetObjects("Select objects to mirror")
  233. if objs:
  234. plane = rs.ViewCPlane()
  235. xform = rs.XformMirror(plane.Origin, plane.Normal)
  236. rs.TransformObjects( objs, xform, True )
  237. See Also:
  238. XformPlanarProjection
  239. XformRotation1
  240. XformRotation2
  241. XformRotation3
  242. XformRotation4
  243. XformScale
  244. XformShear
  245. XformTranslation
  246. """
  247. point = rhutil.coerce3dpoint(mirror_plane_point, True)
  248. normal = rhutil.coerce3dvector(mirror_plane_normal, True)
  249. return Rhino.Geometry.Transform.Mirror(point, normal)
  250. def XformMultiply(xform1, xform2):
  251. """Multiplies two transformation matrices, where result = xform1 * xform2
  252. Parameters:
  253. xform1 (transform): List or Rhino.Geometry.Transform. The first 4x4 transformation matrix to multiply.
  254. xform2 (transform): List or Rhino.Geometry.Transform. The second 4x4 transformation matrix to multiply.
  255. Returns:
  256. transform: result transformation on success
  257. Example:
  258. import rhinoscriptsyntax as rs
  259. import math
  260. objs = rs.GetObjects("Select objects to shear")
  261. if objs:
  262. cplane = rs.ViewCPlane()
  263. cob = rs.XformChangeBasis(rs.WorldXYPlane(), cplane)
  264. shear2d = rs.XformIdentity()
  265. shear2d[0,2] = math.tan(math.radians(45.0))
  266. cob_inv = rs.XformChangeBasis(cplane, rs.WorldXYPlane())
  267. temp = rs.XformMultiply(shear2d, cob)
  268. xform = rs.XformMultiply(cob_inv, temp)
  269. rs.TransformObjects( objs, xform, True )
  270. See Also:
  271. XformPlanarProjection
  272. XformRotation1
  273. XformRotation2
  274. XformRotation3
  275. XformRotation4
  276. XformScale
  277. XformShear
  278. XformTranslation
  279. """
  280. xform1 = rhutil.coercexform(xform1, True)
  281. xform2 = rhutil.coercexform(xform2, True)
  282. return xform1*xform2
  283. def XformPlanarProjection(plane):
  284. """Returns a transformation matrix that projects to a plane.
  285. Parameters:
  286. plane (plane): The plane to project to.
  287. Returns:
  288. transform: The 4x4 transformation matrix.
  289. Example:
  290. import rhinoscriptsyntax as rs
  291. objects = rs.GetObjects("Select objects to project")
  292. if objects:
  293. cplane = rs.ViewCPlane()
  294. xform = rs.XformPlanarProjection(cplane)
  295. rs.TransformObjects( objects, xform, True )
  296. See Also:
  297. XformMirror
  298. XformRotation1
  299. XformRotation2
  300. XformRotation3
  301. XformRotation4
  302. XformScale
  303. XformShear
  304. XformTranslation
  305. """
  306. plane = rhutil.coerceplane(plane, True)
  307. return Rhino.Geometry.Transform.PlanarProjection(plane)
  308. def XformRotation1(initial_plane, final_plane):
  309. """Returns a rotation transformation that maps initial_plane to final_plane.
  310. The planes should be right hand orthonormal planes.
  311. Parameters:
  312. initial_plane (plane): plane to rotate from
  313. final_plane (plane): plane to rotate to
  314. Returns:
  315. transform: The 4x4 transformation matrix.
  316. None: on error.
  317. Example:
  318. See Also:
  319. """
  320. initial_plane = rhutil.coerceplane(initial_plane, True)
  321. final_plane = rhutil.coerceplane(final_plane, True)
  322. xform = Rhino.Geometry.Transform.PlaneToPlane(initial_plane, final_plane)
  323. if not xform.IsValid: return scriptcontext.errorhandler()
  324. return xform
  325. def XformRotation2(angle_degrees, rotation_axis, center_point):
  326. """Returns a rotation transformation around an axis
  327. Parameters:
  328. angle_degrees (number): rotation angle in degrees
  329. rotation_axis (vector): rotation axis
  330. center_point (point): rotation center
  331. Returns:
  332. transform: The 4x4 transformation matrix.
  333. None: on error.
  334. Example:
  335. See Also:
  336. """
  337. axis = rhutil.coerce3dvector(rotation_axis, True)
  338. center = rhutil.coerce3dpoint(center_point, True)
  339. angle_rad = math.radians(angle_degrees)
  340. xform = Rhino.Geometry.Transform.Rotation(angle_rad, axis, center)
  341. if not xform.IsValid: return scriptcontext.errorhandler()
  342. return xform
  343. def XformRotation3( start_direction, end_direction, center_point ):
  344. """Calculate the minimal transformation that rotates start_direction to
  345. end_direction while fixing center_point
  346. Parameters:
  347. start_direction, end_direction (vector): 3d vectors
  348. center_point (point): the rotation center
  349. Returns:
  350. transform: The 4x4 transformation matrix.
  351. None: on error.
  352. Example:
  353. See Also:
  354. """
  355. start = rhutil.coerce3dvector(start_direction, True)
  356. end = rhutil.coerce3dvector(end_direction, True)
  357. center = rhutil.coerce3dpoint(center_point, True)
  358. xform = Rhino.Geometry.Transform.Rotation(start, end, center)
  359. if not xform.IsValid: return scriptcontext.errorhandler()
  360. return xform
  361. def XformRotation4(x0, y0, z0, x1, y1, z1):
  362. """Returns a rotation transformation.
  363. Parameters:
  364. x0,y0,z0 (vector): Vectors defining the initial orthonormal frame
  365. x1,y1,z1 (vector): Vectors defining the final orthonormal frame
  366. Returns:
  367. transform: The 4x4 transformation matrix.
  368. None: on error.
  369. Example:
  370. See Also:
  371. """
  372. x0 = rhutil.coerce3dvector(x0, True)
  373. y0 = rhutil.coerce3dvector(y0, True)
  374. z0 = rhutil.coerce3dvector(z0, True)
  375. x1 = rhutil.coerce3dvector(x1, True)
  376. y1 = rhutil.coerce3dvector(y1, True)
  377. z1 = rhutil.coerce3dvector(z1, True)
  378. xform = Rhino.Geometry.Transform.Rotation(x0,y0,z0,x1,y1,z1)
  379. if not xform.IsValid: return scriptcontext.errorhandler()
  380. return xform
  381. def XformScale(scale, point=None):
  382. """Creates a scale transformation
  383. Parameters:
  384. scale (number|point|vector|[number, number, number]): single number, list of 3 numbers, Point3d, or Vector3d
  385. point (point, optional): center of scale. If omitted, world origin is used
  386. Returns:
  387. transform: The 4x4 transformation matrix on success
  388. None: on error
  389. Example:
  390. import rhinoscriptsyntax as rs
  391. objs = rs.GetObjects("Select objects to scale")
  392. if objs:
  393. xform = rs.XformScale( (3.0,1.0,1.0) )
  394. rs.TransformObjects( objs, xform, True)
  395. See Also:
  396. XformMirror
  397. XformPlanarProjection
  398. XformRotation1
  399. XformRotation2
  400. XformRotation3
  401. XformRotation4
  402. XformShear
  403. XformTranslation
  404. """
  405. factor = rhutil.coerce3dpoint(scale)
  406. if factor is None:
  407. if type(scale) is int or type(scale) is float:
  408. factor = (scale,scale,scale)
  409. if factor is None: return scriptcontext.errorhandler()
  410. if point: point = rhutil.coerce3dpoint(point, True)
  411. else: point = Rhino.Geometry.Point3d.Origin
  412. plane = Rhino.Geometry.Plane(point, Rhino.Geometry.Vector3d.ZAxis);
  413. xf = Rhino.Geometry.Transform.Scale(plane, factor[0], factor[1], factor[2])
  414. return xf
  415. def XformScreenToWorld(point, view=None, screen_coordinates=False):
  416. """Transforms a point from either client-area coordinates of the specified view
  417. or screen coordinates to world coordinates. The resulting coordinates are represented
  418. as a 3-D point
  419. Parameters:
  420. point (point): 2D point
  421. view (str, optional): title or identifier of a view. If omitted, the active view is used
  422. screen_coordinates (bool, optional): if False, point is in client-area coordinates. If True,
  423. point is in screen-area coordinates
  424. Returns:
  425. point: on success
  426. None: on error
  427. Example:
  428. import rhinoscriptsyntax as rs
  429. point2d = 200,100
  430. view = rs.CurrentView()
  431. point = rs.XformScreenToWorld(point2d, view)
  432. print point
  433. See Also:
  434. XformWorldToScreen
  435. """
  436. point = rhutil.coerce2dpoint(point, True)
  437. view = rhview.__viewhelper(view)
  438. viewport = view.MainViewport
  439. xform = viewport.GetTransform(Rhino.DocObjects.CoordinateSystem.Screen, Rhino.DocObjects.CoordinateSystem.World)
  440. point3d = Rhino.Geometry.Point3d(point.X, point.Y, 0)
  441. if screen_coordinates:
  442. screen = view.ScreenRectangle
  443. point3d.X = point.X - screen.Left
  444. point3d.Y = point.Y - screen.Top
  445. point3d = xform * point3d
  446. return point3d
  447. def XformShear(plane, x, y, z):
  448. """Returns a shear transformation matrix
  449. Parameters:
  450. plane (plane): plane[0] is the fixed point
  451. x,y,z (number): each axis scale factor
  452. Returns:
  453. transform: The 4x4 transformation matrix on success
  454. Example:
  455. import rhinoscriptsyntax as rs
  456. objects = rs.GetObjects("Select objects to shear")
  457. if objects:
  458. cplane = rs.ViewCPlane()
  459. xform = rs.XformShear(cplane, (1,1,0), (-1,1,0), (0,0,1))
  460. rs.TransformObjects(objects, xform, True)
  461. See Also:
  462. XformMirror
  463. XformPlanarProjection
  464. XformRotation1
  465. XformRotation2
  466. XformRotation3
  467. XformRotation4
  468. XformScale
  469. XformTranslation
  470. """
  471. plane = rhutil.coerceplane(plane, True)
  472. x = rhutil.coerce3dvector(x, True)
  473. y = rhutil.coerce3dvector(y, True)
  474. z = rhutil.coerce3dvector(z, True)
  475. return Rhino.Geometry.Transform.Shear(plane,x,y,z)
  476. def XformTranslation(vector):
  477. """Creates a translation transformation matrix
  478. Parameters:
  479. vector (vector): List of 3 numbers, Point3d, or Vector3d. A 3-D translation vector.
  480. Returns:
  481. transform: The 4x4 transformation matrix is successful, otherwise None
  482. Example:
  483. import rhinoscriptsyntax as rs
  484. objs = rs.GetObjects("Select objects to copy")
  485. if objs:
  486. xform = rs.XformTranslation([1,0,0])
  487. rs.TransformObjects( objs, xform, True )
  488. See Also:
  489. XformMirror
  490. XformPlanarProjection
  491. XformRotation1
  492. XformRotation2
  493. XformRotation3
  494. XformRotation4
  495. XformScale
  496. XformShear
  497. """
  498. vector = rhutil.coerce3dvector(vector, True)
  499. return Rhino.Geometry.Transform.Translation(vector)
  500. def XformWorldToCPlane(point, plane):
  501. """Transforms a point from world coordinates to construction plane coordinates.
  502. Parameters:
  503. point (point): A 3D point in world coordinates.
  504. plane (plane): The construction plane
  505. Returns:
  506. (point): 3D point in construction plane coordinates
  507. Example:
  508. import rhinoscriptsyntax as rs
  509. plane = rs.ViewCPlane()
  510. point = rs.XformWorldToCPlane([0,0,0], plane)
  511. if point: print "CPlane point:", point
  512. See Also:
  513. XformCPlaneToWorld
  514. """
  515. point = rhutil.coerce3dpoint(point, True)
  516. plane = rhutil.coerceplane(plane, True)
  517. v = point - plane.Origin;
  518. return Rhino.Geometry.Point3d(v*plane.XAxis, v*plane.YAxis, v*plane.ZAxis)
  519. def XformWorldToScreen(point, view=None, screen_coordinates=False):
  520. """Transforms a point from world coordinates to either client-area coordinates of
  521. the specified view or screen coordinates. The resulting coordinates are represented
  522. as a 2D point
  523. Parameters:
  524. point (point): 3D point in world coordinates
  525. view (str, optional): title or identifier of a view. If omitted, the active view is used
  526. screen_coordinates (bool, optional): if False, the function returns the results as
  527. client-area coordinates. If True, the result is in screen-area coordinates
  528. Returns:
  529. (point): 2D point on success
  530. None: on error
  531. Example:
  532. import rhinoscriptsyntax as rs
  533. point = (0.0, 0.0, 0.0)
  534. view = rs.CurrentView()
  535. point2d = rs.XformWorldToScreen(point, view)
  536. print point2d
  537. See Also:
  538. XformScreenToWorld
  539. """
  540. point = rhutil.coerce3dpoint(point, True)
  541. view = rhview.__viewhelper(view)
  542. viewport = view.MainViewport
  543. xform = viewport.GetTransform(Rhino.DocObjects.CoordinateSystem.World, Rhino.DocObjects.CoordinateSystem.Screen)
  544. point = xform * point
  545. point = Rhino.Geometry.Point2d(point.X, point.Y)
  546. if screen_coordinates:
  547. screen = view.ScreenRectangle
  548. point.X = point.X + screen.Left
  549. point.Y = point.Y + screen.Top
  550. return point
  551. def XformZero():
  552. """Returns a zero transformation matrix
  553. Returns:
  554. transform: a zero transformation matrix
  555. Example:
  556. import rhinoscriptsyntax as rs
  557. def printmatrix(xform):
  558. for i in range(4):
  559. print "[", xform[i,0], ", ", xform[i,1], ", ", xform[i,2], ", ", xform[i,3], "]"
  560. printmatrix( rs.XformZero() )
  561. See Also:
  562. XformDiagonal
  563. XformIdentity
  564. """
  565. return Rhino.Geometry.Transform()