GLGeometryCoordinates.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. unit GLGeometryCoordinates;
  5. (*
  6. Helper functions to convert between different three dimensional coordinate
  7. systems. Room for optimisations.
  8. *)
  9. interface
  10. {$I GLScene.inc}
  11. uses
  12. System.Math,
  13. GLVectorGeometry;
  14. // Convert cylindrical to cartesian [single]. theta in rad
  15. procedure Cylindrical_Cartesian(const r, theta, z1: single; var x, y, z: single); overload;
  16. // Convert cylindrical to cartesian [double]. theta in rads
  17. procedure Cylindrical_Cartesian(const r, theta, z1: double; var x, y, z: double); overload;
  18. // Convert cylindrical to cartesian [single] (with error check). theta in rad
  19. procedure Cylindrical_Cartesian(const r, theta, z1: single; var x, y, z: single;
  20. var ierr: integer); overload;
  21. // Convert cylindrical to cartesian [double] (with error check). theta in rad
  22. procedure Cylindrical_Cartesian(const r, theta, z1: double; var x, y, z: double;
  23. var ierr: integer); overload;
  24. // Convert cartesian to cylindrical [single]
  25. procedure Cartesian_Cylindrical(const x, y, z1: single; var r, theta, z: single); overload;
  26. // Convert cartesion to cylindrical [double]
  27. procedure Cartesian_Cylindrical(const x, y, z1: double; var r, theta, z: double); overload;
  28. // Convert spherical to cartesion. [single] theta,phi in rads
  29. procedure Spherical_Cartesian(const r, theta, phi: single; var x, y, z: single); overload;
  30. // Convert spherical to cartesion. [double] theta,phi in rads
  31. procedure Spherical_Cartesian(const r, theta, phi: double; var x, y, z: double); overload;
  32. // Convert spherical to cartesian [single] (with error check).theta,phi in rad
  33. procedure Spherical_Cartesian(const r, theta, phi: single; var x, y, z: single;
  34. var ierr: integer); overload;
  35. // Convert spherical to cartesian [double] (with error check).theta,phi in rad
  36. procedure Spherical_Cartesian(const r, theta, phi: double; var x, y, z: double;
  37. var ierr: integer); overload;
  38. // Convert cartesian to spherical [single]
  39. procedure Cartesian_Spherical(const x, y, z: single; var r, theta, phi: single); overload;
  40. procedure Cartesian_Spherical(const v: TAffineVector; var r, theta, phi: single); overload;
  41. // Convert cartesion to spherical [double]
  42. procedure Cartesian_Spherical(const x, y, z: double; var r, theta, phi: double); overload;
  43. // Convert Prolate-Spheroidal to Cartesian. [single] eta, phi in rad
  44. procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: single;
  45. var x, y, z: single); overload;
  46. // Convert Prolate-Spheroidal to Cantesian. [double] eta,phi in rad
  47. procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: double;
  48. var x, y, z: double); overload;
  49. // Convert Prolate-Spheroidal to Cartesian [single](with error check). eta,phi in rad
  50. procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: single;
  51. var x, y, z: single; var ierr: integer); overload;
  52. // Convert Prolate-Spheroidal to Cartesian [single](with error check). eta,phi in rad
  53. procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: double;
  54. var x, y, z: double; var ierr: integer); overload;
  55. // Convert Oblate-Spheroidal to Cartesian. [Single] eta, phi in rad
  56. procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: single;
  57. var x, y, z: single); overload;
  58. // Convert Oblate-Spheroidal to Cartesian. [Double] eta, phi in rad
  59. procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: double;
  60. var x, y, z: double); overload;
  61. // Convert Oblate-Spheroidal to Cartesian (with error check). eta,phi in rad
  62. procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: single;
  63. var x, y, z: single; var ierr: integer); overload;
  64. // Convert Oblate-Spheroidal to Cartesian (with error check).[Double] eta,phi in rad
  65. procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: double;
  66. var x, y, z: double; var ierr: integer); overload;
  67. // Convert Bipolar to Cartesian. u in rad
  68. procedure BipolarCylindrical_Cartesian(const u, v, z1, a: single;
  69. var x, y, z: single); overload;
  70. // Convert Bipolar to Cartesian. [Double] u in rad
  71. procedure BipolarCylindrical_Cartesian(const u, v, z1, a: double;
  72. var x, y, z: double); overload;
  73. // Convert Bipolar to Cartesian (with error check). u in rad
  74. procedure BipolarCylindrical_Cartesian(const u, v, z1, a: single;
  75. var x, y, z: single; var ierr: integer); overload;
  76. // Convert Bipolar to Cartesian (with error check). [Double] u in rad
  77. procedure BipolarCylindrical_Cartesian(const u, v, z1, a: double;
  78. var x, y, z: double; var ierr: integer); overload;
  79. // --------------------------------------------------------------------------
  80. implementation
  81. // --------------------------------------------------------------------------
  82. // ----- Cylindrical_Cartesian ---------------------------------------------
  83. (* Convert Cylindrical to Cartesian with no checks.
  84. Ref: http://mathworld.wolfram.com/CylindricalCoordinates.html *)
  85. procedure Cylindrical_Cartesian(const r, theta, z1: single; var x, y, z: single);
  86. begin
  87. SinCosine(theta, r, y, x);
  88. z := z1;
  89. end;
  90. // ----- Cylindrical_Cartesian -------------------------------------------------
  91. (* Convert Cylindrical to Cartesian with no checks. Double version
  92. Ref: http://mathworld.wolfram.com/CylindricalCoordinates.html *)
  93. procedure Cylindrical_Cartesian(const r, theta, z1: double; var x, y, z: double);
  94. begin
  95. SinCosine(theta, r, y, x);
  96. z := z1;
  97. end;
  98. // ----- Cylindrical_Cartesian -------------------------------------------------
  99. (* Convert Cylindrical to Cartesian with checks.
  100. ierr: [0] = ok,
  101. [1] = r out of bounds. Acceptable r: [0,inf)
  102. [2] = theta out of bounds. Acceptable theta: [0,2pi)
  103. [3] = z1 out of bounds. Acceptable z1 : (-inf,inf)
  104. Ref: http://mathworld.wolfram.com/CylindricalCoordinates.html *)
  105. procedure Cylindrical_Cartesian(const r, theta, z1: single; var x, y, z: single;
  106. var ierr: integer);
  107. begin
  108. // check input parameters
  109. if (r < 0.0) then
  110. ierr := 1
  111. else if ((theta < 0.0) or (theta >= 2 * pi)) then
  112. ierr := 2
  113. else
  114. ierr := 0;
  115. if (ierr = 0) then
  116. begin
  117. SinCosine(theta, r, y, x);
  118. z := z1;
  119. end;
  120. end;
  121. // ----- Cylindrical_Cartesian -------------------------------------------------
  122. (* Convert Cylindrical to Cartesian with checks.
  123. ierr: [0] = ok,
  124. [1] = r out of bounds. Acceptable r: [0,inf)
  125. [2] = theta out of bounds. Acceptable theta: [0,2pi)
  126. [3] = z1 out of bounds. Acceptable z1 : (-inf,inf)
  127. Ref: http://mathworld.wolfram.com/CylindricalCoordinates.html *)
  128. procedure Cylindrical_Cartesian(const r, theta, z1: double; var x, y, z: double;
  129. var ierr: integer);
  130. begin
  131. // check input parameters
  132. if (r < 0.0) then
  133. ierr := 1
  134. else if ((theta < 0.0) or (theta >= 2 * pi)) then
  135. ierr := 2
  136. else
  137. ierr := 0;
  138. if (ierr = 0) then
  139. begin
  140. SinCosine(theta, r, y, x);
  141. z := z1;
  142. end;
  143. end;
  144. // ----- Cartesian_Cylindrical -------------------------------------------------
  145. (* Convert Cartesian to Cylindrical no checks. Single *)
  146. procedure Cartesian_Cylindrical(const x, y, z1: single; var r, theta, z: single);
  147. begin
  148. r := sqrt(x * x + y * y);
  149. theta := ArcTan2(y, x);
  150. z := z1;
  151. end;
  152. // ----- Cartesian_Cylindrical -------------------------------------------------
  153. (* Convert Cartesian to Cylindrical no checks. Duoble *)
  154. procedure Cartesian_Cylindrical(const x, y, z1: double; var r, theta, z: double);
  155. begin
  156. r := sqrt(x * x + y * y);
  157. theta := ArcTan2(y, x);
  158. z := z1;
  159. end;
  160. // ----- Spherical_Cartesian ---------------------------------------------------
  161. (* Convert Spherical to Cartesian with no checks.
  162. Ref: http://mathworld.wolfram.com/SphericalCoordinates.html *)
  163. procedure Spherical_Cartesian(const r, theta, phi: single; var x, y, z: single);
  164. var
  165. a: single;
  166. begin
  167. SinCosine(phi, r, a, z); // z = r*cos(phi), a=r*sin(phi)
  168. SinCosine(theta, a, y, x); // x = a*cos(theta), y = a*sin(theta)}
  169. end;
  170. // ----- Spherical_Cartesian ---------------------------------------------------
  171. (* Convert Spherical to Cartesian with no checks. Double version.
  172. Ref: http://mathworld.wolfram.com/SphericalCoordinates.html *)
  173. procedure Spherical_Cartesian(const r, theta, phi: double; var x, y, z: double);
  174. var
  175. a: double;
  176. begin
  177. SinCosine(phi, r, a, z); // z = r*cos(phi), a=r*sin(phi)
  178. SinCosine(theta, a, y, x); // x = a*cos(theta), y = a*sin(theta)}
  179. end;
  180. // ----- Spherical_Cartesian ---------------------------------------------------
  181. (* Convert Spherical to Cartesian with checks.
  182. ierr: [0] = ok,
  183. [1] = r out of bounds
  184. [2] = theta out of bounds
  185. [3] = phi out of bounds
  186. Ref: http://mathworld.wolfram.com/SphericalCoordinates.html *)
  187. procedure Spherical_Cartesian(const r, theta, phi: single; var x, y, z: single;
  188. var ierr: integer);
  189. var
  190. a: single;
  191. begin
  192. if (r < 0.0) then
  193. ierr := 1
  194. else if ((theta < 0.0) or (theta >= 2 * pi)) then
  195. ierr := 2
  196. else if ((phi < 0.0) or (phi >= 2 * pi)) then
  197. ierr := 3
  198. else
  199. ierr := 0;
  200. if (ierr = 0) then
  201. begin
  202. SinCosine(phi, r, a, z); // z = r*cos(phi), a=r*sin(phi)
  203. SinCosine(theta, a, y, x); // x = a*cos(theta), y = a*sin(theta)}
  204. end;
  205. end;
  206. // ----- Spherical_Cartesian ---------------------------------------------------
  207. (* Convert Spherical to Cartesian with checks.
  208. ierr: [0] = ok,
  209. [1] = r out of bounds
  210. [2] = theta out of bounds
  211. [3] = phi out of bounds
  212. Ref: http://mathworld.wolfram.com/SphericalCoordinates.html *)
  213. procedure Spherical_Cartesian(const r, theta, phi: double; var x, y, z: double;
  214. var ierr: integer);
  215. var
  216. a: double;
  217. begin
  218. if (r < 0.0) then
  219. ierr := 1
  220. else if ((theta < 0.0) or (theta >= 2 * pi)) then
  221. ierr := 2
  222. else if ((phi < 0.0) or (phi >= 2 * pi)) then
  223. ierr := 3
  224. else
  225. ierr := 0;
  226. if (ierr = 0) then
  227. begin
  228. SinCosine(phi, r, a, z); // z = r*cos(phi), a=r*sin(phi)
  229. SinCosine(theta, a, y, x); // x = a*cos(theta), y = a*sin(theta)}
  230. end;
  231. end;
  232. // ----- Cartesian_Spherical ---------------------------------------------------
  233. (* convert Cartesian to Spherical, no checks, single
  234. Ref: http://mathworld.wolfram.com/SphericalCoordinates.html
  235. NB: Could be optimised by using jclmath.pas unit? *)
  236. procedure Cartesian_Spherical(const x, y, z: single; var r, theta, phi: single);
  237. begin
  238. r := sqrt((x * x) + (y * y) + (z * z));
  239. theta := ArcTan2(y, x);
  240. phi := ArcCosine(z / r);
  241. end;
  242. procedure Cartesian_Spherical(const v: TAffineVector; var r, theta, phi: single);
  243. begin
  244. r := VectorLength(v);
  245. theta := ArcTan2(v.y, v.x);
  246. phi := ArcCosine(v.z / r);
  247. end;
  248. // ----- Cartesian_Spherical ---------------------------------------------------
  249. (* convert Cartesian to Spherical, no checks, double
  250. Ref: http://mathworld.wolfram.com/SphericalCoordinates.html
  251. NB: Could be optimised by using jclmath.pas unit? *)
  252. procedure Cartesian_Spherical(const x, y, z: double; var r, theta, phi: double);
  253. begin
  254. r := sqrt((x * x) + (y * y) + (z * z));
  255. theta := ArcTan2(y, x);
  256. phi := ArcCosine(z / r);
  257. end;
  258. // ----- ProlateSpheroidal_Cartesian -------------------------------------------
  259. (* Convert Prolate-Spheroidal to Cartesian with no checks.
  260. A system of curvilinear coordinates in which two sets of coordinate surfaces are
  261. obtained by revolving the curves of the elliptic cylindrical coordinates about
  262. the x-axis, which is relabeled the z-axis. The third set of coordinates
  263. consists of planes passing through this axis.
  264. The coordinate system is parameterised by parameter a. A default value of a=1 is
  265. suggesed:
  266. http://documents.wolfram.com/v4/AddOns/StandardPackages/Calculus/VectorAnalysis.html
  267. Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
  268. procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: single; var x, y, z: single);
  269. var
  270. sn, cs, snphi, csphi, shx, chx: single;
  271. begin
  272. SinCosine(eta, a, sn, cs);
  273. SinCosine(phi, snphi, csphi);
  274. shx := sinh(xi);
  275. chx := cosh(xi);
  276. x := sn * shx * csphi; // x = a*sin(eta)*sinh(xi)*cos(phi)
  277. y := sn * shx * snphi; // y = a*sin(eta)*sinh(xi)*sin(phi)
  278. z := cs * chx; // z = a*cos(eta)*cosh(xi)
  279. end;
  280. // ----- ProlateSpheroidal_Cartesian -------------------------------------------
  281. (* Convert Prolate-Spheroidal to Cartesian with no checks. Double version.
  282. A system of curvilinear coordinates in which two sets of coordinate surfaces are
  283. obtained by revolving the curves of the elliptic cylindrical coordinates about
  284. the x-axis, which is relabeled the z-axis. The third set of coordinates
  285. consists of planes passing through this axis.
  286. The coordinate system is parameterised by parameter a. A default value of a=1 is
  287. suggesed:
  288. http://documents.wolfram.com/v4/AddOns/StandardPackages/Calculus/VectorAnalysis.html
  289. Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
  290. procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: double; var x, y, z: double);
  291. var
  292. sn, cs, snphi, csphi, shx, chx: double;
  293. begin
  294. SinCosine(eta, a, sn, cs);
  295. SinCosine(phi, snphi, csphi);
  296. shx := sinh(xi);
  297. chx := cosh(xi);
  298. x := sn * shx * csphi; // x = a*sin(eta)*sinh(xi)*cos(phi)
  299. y := sn * shx * snphi; // y = a*sin(eta)*sinh(xi)*sin(phi)
  300. z := cs * chx; // z = a*cos(eta)*cosh(xi)
  301. end;
  302. // ----- ProlateSpheroidal_Cartesian -------------------------------------------
  303. (* Convert Prolate-Spheroidal to Cartesian with checks.
  304. ierr: [0] = ok,
  305. [1] = xi out of bounds. Acceptable xi: [0,inf)
  306. [2] = eta out of bounds. Acceptable eta: [0,pi]
  307. [3] = phi out of bounds. Acceptable phi: [0,2pi)
  308. Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
  309. procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: single;
  310. var x, y, z: single; var ierr: integer); overload;
  311. var
  312. sn, cs, snphi, csphi, shx, chx: single;
  313. begin
  314. if (xi < 0.0) then
  315. ierr := 1
  316. else if ((eta < 0.0) or (eta > pi)) then
  317. ierr := 2
  318. else if ((phi < 0.0) or (phi >= 2 * pi)) then
  319. ierr := 3
  320. else
  321. ierr := 0;
  322. if (ierr = 0) then
  323. begin
  324. SinCosine(eta, a, sn, cs);
  325. SinCosine(phi, snphi, csphi);
  326. shx := sinh(xi);
  327. chx := cosh(xi);
  328. x := sn * shx * csphi; // x = a*sin(eta)*sinh(xi)*cos(phi)
  329. y := sn * shx * snphi; // y = a*sin(eta)*sinh(xi)*sin(phi)
  330. z := cs * chx; // z = a*cos(eta)*cosh(xi)
  331. end;
  332. end;
  333. // ----- ProlateSpheroidal_Cartesian -------------------------------------------
  334. (* Convert Prolate-Spheroidal to Cartesian with checks. Double Version.
  335. ierr: [0] = ok,
  336. [1] = xi out of bounds. Acceptable xi: [0,inf)
  337. [2] = eta out of bounds. Acceptable eta: [0,pi]
  338. [3] = phi out of bounds. Acceptable phi: [0,2pi)
  339. Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
  340. procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: double;
  341. var x, y, z: double; var ierr: integer); overload;
  342. var
  343. sn, cs, snphi, csphi, shx, chx: double;
  344. begin
  345. if (xi < 0.0) then
  346. ierr := 1
  347. else if ((eta < 0.0) or (eta > pi)) then
  348. ierr := 2
  349. else if ((phi < 0.0) or (phi >= 2 * pi)) then
  350. ierr := 3
  351. else
  352. ierr := 0;
  353. if (ierr = 0) then
  354. begin
  355. SinCosine(eta, a, sn, cs);
  356. SinCosine(phi, snphi, csphi);
  357. shx := sinh(xi);
  358. chx := cosh(xi);
  359. x := sn * shx * csphi; // x = a*sin(eta)*sinh(xi)*cos(phi)
  360. y := sn * shx * snphi; // y = a*sin(eta)*sinh(xi)*sin(phi)
  361. z := cs * chx; // z = a*cos(eta)*cosh(xi)
  362. end;
  363. end;
  364. // ----- OblateSpheroidal_Cartesian -------------------------------------------
  365. (* Convert Oblate-Spheroidal to Cartesian with no checks.
  366. A system of curvilinear coordinates in which two sets of coordinate surfaces are
  367. obtained by revolving the curves of the elliptic cylindrical coordinates about
  368. the y-axis which is relabeled the z-axis. The third set of coordinates consists
  369. of planes passing through this axis.
  370. The coordinate system is parameterised by parameter a. A default value of a=1 is
  371. suggesed:
  372. http://documents.wolfram.com/v4/AddOns/StandardPackages/Calculus/VectorAnalysis.html
  373. Ref: http://mathworld.wolfram.com/OblateSpheroidalCoordinates.html *)
  374. procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: single; var x, y, z: single);
  375. var
  376. sn, cs, snphi, csphi, shx, chx: single;
  377. begin
  378. SinCosine(eta, a, sn, cs);
  379. SinCosine(phi, snphi, csphi);
  380. shx := sinh(xi);
  381. chx := cosh(xi);
  382. x := cs * chx * csphi; // x = a*cos(eta)*cosh(xi)*cos(phi)
  383. y := cs * chx * snphi; // y = a*cos(eta)*cosh(xi)*sin(phi)
  384. z := sn * shx; // z = a*sin(eta)*sinh(xi)
  385. end;
  386. // ----- OblateSpheroidal_Cartesian -------------------------------------------
  387. (* Convert Oblate-Spheroidal to Cartesian with no checks. Double Version.
  388. A system of curvilinear coordinates in which two sets of coordinate surfaces are
  389. obtained by revolving the curves of the elliptic cylindrical coordinates about
  390. the y-axis which is relabeled the z-axis. The third set of coordinates consists
  391. of planes passing through this axis.
  392. The coordinate system is parameterised by parameter a. A default value of a=1 is
  393. suggesed:
  394. http://documents.wolfram.com/v4/AddOns/StandardPackages/Calculus/VectorAnalysis.html
  395. Ref: http://mathworld.wolfram.com/OblateSpheroidalCoordinates.html *)
  396. procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: double; var x, y, z: double);
  397. var
  398. sn, cs, snphi, csphi, shx, chx: double;
  399. begin
  400. SinCosine(eta, a, sn, cs);
  401. SinCosine(phi, snphi, csphi);
  402. shx := sinh(xi);
  403. chx := cosh(xi);
  404. x := cs * chx * csphi; // x = a*cos(eta)*cosh(xi)*cos(phi)
  405. y := cs * chx * snphi; // y = a*cos(eta)*cosh(xi)*sin(phi)
  406. z := sn * shx; // z = a*sin(eta)*sinh(xi)
  407. end;
  408. // ----- OblateSpheroidal_Cartesian -------------------------------------------
  409. (* Convert Oblate-Spheroidal to Cartesian with checks.
  410. ierr: [0] = ok,
  411. [1] = xi out of bounds. Acceptable xi: [0,inf)
  412. [2] = eta out of bounds. Acceptable eta: [-0.5*pi,0.5*pi]
  413. [3] = phi out of bounds. Acceptable phi: [0,2*pi)
  414. Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
  415. procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: single;
  416. var x, y, z: single; var ierr: integer); overload;
  417. var
  418. sn, cs, snphi, csphi, shx, chx: single;
  419. begin
  420. if (xi < 0.0) then
  421. ierr := 1
  422. else if ((eta < -0.5 * pi) or (eta > 0.5 * pi)) then
  423. ierr := 2
  424. else if ((phi < 0.0) or (phi >= 2 * pi)) then
  425. ierr := 3
  426. else
  427. ierr := 0;
  428. if (ierr = 0) then
  429. begin
  430. SinCosine(eta, a, sn, cs);
  431. SinCosine(phi, snphi, csphi);
  432. shx := sinh(xi);
  433. chx := cosh(xi);
  434. x := cs * chx * csphi; // x = a*cos(eta)*cosh(xi)*cos(phi)
  435. y := cs * chx * snphi; // y = a*cos(eta)*cosh(xi)*sin(phi)
  436. z := sn * shx; // z = a*sin(eta)*sinh(xi)
  437. end;
  438. end;
  439. // ----- OblateSpheroidal_Cartesian -------------------------------------------
  440. (* Convert Oblate-Spheroidal to Cartesian with checks. Double Version.
  441. ierr: [0] = ok,
  442. [1] = xi out of bounds. Acceptable xi: [0,inf)
  443. [2] = eta out of bounds. Acceptable eta: [-0.5*pi,0.5*pi]
  444. [3] = phi out of bounds. Acceptable phi: [0,2*pi)
  445. Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
  446. procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: double;
  447. var x, y, z: double; var ierr: integer); overload;
  448. var
  449. sn, cs, snphi, csphi, shx, chx: double;
  450. begin
  451. if (xi < 0.0) then
  452. ierr := 1
  453. else if ((eta < -0.5 * pi) or (eta > 0.5 * pi)) then
  454. ierr := 2
  455. else if ((phi < 0.0) or (phi >= 2 * pi)) then
  456. ierr := 3
  457. else
  458. ierr := 0;
  459. if (ierr = 0) then
  460. begin
  461. SinCosine(eta, a, sn, cs);
  462. SinCosine(phi, snphi, csphi);
  463. shx := sinh(xi);
  464. chx := cosh(xi);
  465. x := cs * chx * csphi; // x = a*cos(eta)*cosh(xi)*cos(phi)
  466. y := cs * chx * snphi; // y = a*cos(eta)*cosh(xi)*sin(phi)
  467. z := sn * shx; // z = a*sin(eta)*sinh(xi)
  468. end;
  469. end;
  470. // ----- BipolarCylindrical_Cartesian ------------------------------------------
  471. (* Convert BiPolarCylindrical to Cartesian with no checks.
  472. http://mathworld.wolfram.com/BipolarCylindricalCoordinates.html *)
  473. procedure BipolarCylindrical_Cartesian(const u, v, z1, a: single; var x, y, z: single);
  474. var
  475. cs, sn, shx, chx: single;
  476. begin
  477. SinCosine(u, sn, cs);
  478. shx := sinh(v);
  479. chx := cosh(v);
  480. x := a * shx / (chx - cs);
  481. y := a * sn / (chx - cs);
  482. z := z1;
  483. end;
  484. // ----- BipolarCylindrical_Cartesian ------------------------------------------
  485. (* Convert BiPolarCylindrical to Cartesian with no checks. Double Version
  486. http://mathworld.wolfram.com/BipolarCylindricalCoordinates.html *)
  487. procedure BipolarCylindrical_Cartesian(const u, v, z1, a: double; var x, y, z: double);
  488. var
  489. cs, sn, shx, chx: double;
  490. begin
  491. SinCosine(u, sn, cs);
  492. shx := sinh(v);
  493. chx := cosh(v);
  494. x := a * shx / (chx - cs);
  495. y := a * sn / (chx - cs);
  496. z := z1;
  497. end;
  498. // ----- BipolarCylindrical_Cartesian ------------------------------------------
  499. (* Convert Oblate-Spheroidal to Cartesian with checks.
  500. ierr: [0] = ok,
  501. [1] = u out of bounds. Acceptable u: [0,2*pi)
  502. [2] = v out of bounds. Acceptable v: (-inf,inf)
  503. [3] = z1 out of bounds. Acceptable z1: (-inf,inf)
  504. Ref: http://mathworld.wolfram.com/BiPolarCylindricalCoordinates.html *)
  505. procedure BipolarCylindrical_Cartesian(const u, v, z1, a: single;
  506. var x, y, z: single; var ierr: integer); overload;
  507. var
  508. cs, sn, shx, chx: single;
  509. begin
  510. if ((u < 0.0) or (u >= 2 * pi)) then
  511. ierr := 1
  512. else
  513. ierr := 0;
  514. if (ierr = 0) then
  515. begin
  516. SinCosine(u, sn, cs);
  517. shx := sinh(v);
  518. chx := cosh(v);
  519. x := a * shx / (chx - cs);
  520. y := a * sn / (chx - cs);
  521. z := z1;
  522. end;
  523. end;
  524. // ----- BipolarCylindrical_Cartesian ------------------------------------------
  525. (* Convert Oblate-Spheroidal to Cartesian with checks. Double Version
  526. ierr: [0] = ok,
  527. [1] = u out of bounds. Acceptable u: [0,2*pi)
  528. [2] = v out of bounds. Acceptable v: (-inf,inf)
  529. [3] = z1 out of bounds. Acceptable z1: (-inf,inf)
  530. Ref: http://mathworld.wolfram.com/BiPolarCylindricalCoordinates.html *)
  531. procedure BipolarCylindrical_Cartesian(const u, v, z1, a: double;
  532. var x, y, z: double; var ierr: integer); overload;
  533. var
  534. cs, sn, shx, chx: double;
  535. begin
  536. if ((u < 0.0) or (u >= 2 * pi)) then
  537. ierr := 1
  538. else
  539. ierr := 0;
  540. if (ierr = 0) then
  541. begin
  542. SinCosine(u, sn, cs);
  543. shx := sinh(v);
  544. chx := cosh(v);
  545. x := a * shx / (chx - cs);
  546. y := a * sn / (chx - cs);
  547. z := z1;
  548. end;
  549. end;
  550. // =============================================================================
  551. end.