CurveExtras.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. import {
  2. Curve,
  3. Vector3
  4. } from 'three';
  5. /**
  6. * A bunch of parametric curves
  7. *
  8. * Formulas collected from various sources
  9. * http://mathworld.wolfram.com/HeartCurve.html
  10. * http://en.wikipedia.org/wiki/Viviani%27s_curve
  11. * http://www.mi.sanu.ac.rs/vismath/taylorapril2011/Taylor.pdf
  12. * https://prideout.net/blog/old/blog/index.html@p=44.html
  13. */
  14. /**
  15. * A Granny Knot curve.
  16. *
  17. * @augments Curve
  18. */
  19. class GrannyKnot extends Curve {
  20. /**
  21. * This method returns a vector in 3D space for the given interpolation factor.
  22. *
  23. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  24. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  25. * @return {Vector3} The position on the curve.
  26. */
  27. getPoint( t, optionalTarget = new Vector3() ) {
  28. const point = optionalTarget;
  29. t = 2 * Math.PI * t;
  30. const x = - 0.22 * Math.cos( t ) - 1.28 * Math.sin( t ) - 0.44 * Math.cos( 3 * t ) - 0.78 * Math.sin( 3 * t );
  31. const y = - 0.1 * Math.cos( 2 * t ) - 0.27 * Math.sin( 2 * t ) + 0.38 * Math.cos( 4 * t ) + 0.46 * Math.sin( 4 * t );
  32. const z = 0.7 * Math.cos( 3 * t ) - 0.4 * Math.sin( 3 * t );
  33. return point.set( x, y, z ).multiplyScalar( 20 );
  34. }
  35. }
  36. /**
  37. * A heart curve.
  38. *
  39. * @augments Curve
  40. */
  41. class HeartCurve extends Curve {
  42. /**
  43. * Constructs a new heart curve.
  44. *
  45. * @param {number} [scale=5] - The curve's scale.
  46. */
  47. constructor( scale = 5 ) {
  48. super();
  49. /**
  50. * The curve's scale.
  51. *
  52. * @type {number}
  53. * @default 5
  54. */
  55. this.scale = scale;
  56. }
  57. /**
  58. * This method returns a vector in 3D space for the given interpolation factor.
  59. *
  60. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  61. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  62. * @return {Vector3} The position on the curve.
  63. */
  64. getPoint( t, optionalTarget = new Vector3() ) {
  65. const point = optionalTarget;
  66. t *= 2 * Math.PI;
  67. const x = 16 * Math.pow( Math.sin( t ), 3 );
  68. const y = 13 * Math.cos( t ) - 5 * Math.cos( 2 * t ) - 2 * Math.cos( 3 * t ) - Math.cos( 4 * t );
  69. const z = 0;
  70. return point.set( x, y, z ).multiplyScalar( this.scale );
  71. }
  72. }
  73. /**
  74. * A Viviani curve.
  75. *
  76. * @augments Curve
  77. */
  78. class VivianiCurve extends Curve {
  79. /**
  80. * Constructs a new Viviani curve.
  81. *
  82. * @param {number} [scale=70] - The curve's scale.
  83. */
  84. constructor( scale = 70 ) {
  85. super();
  86. /**
  87. * The curve's scale.
  88. *
  89. * @type {number}
  90. * @default 70
  91. */
  92. this.scale = scale;
  93. }
  94. /**
  95. * This method returns a vector in 3D space for the given interpolation factor.
  96. *
  97. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  98. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  99. * @return {Vector3} The position on the curve.
  100. */
  101. getPoint( t, optionalTarget = new Vector3() ) {
  102. const point = optionalTarget;
  103. t = t * 4 * Math.PI; // normalized to 0..1
  104. const a = this.scale / 2;
  105. const x = a * ( 1 + Math.cos( t ) );
  106. const y = a * Math.sin( t );
  107. const z = 2 * a * Math.sin( t / 2 );
  108. return point.set( x, y, z );
  109. }
  110. }
  111. /**
  112. * A knot curve.
  113. *
  114. * @augments Curve
  115. */
  116. class KnotCurve extends Curve {
  117. /**
  118. * This method returns a vector in 3D space for the given interpolation factor.
  119. *
  120. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  121. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  122. * @return {Vector3} The position on the curve.
  123. */
  124. getPoint( t, optionalTarget = new Vector3() ) {
  125. const point = optionalTarget;
  126. t *= 2 * Math.PI;
  127. const R = 10;
  128. const s = 50;
  129. const x = s * Math.sin( t );
  130. const y = Math.cos( t ) * ( R + s * Math.cos( t ) );
  131. const z = Math.sin( t ) * ( R + s * Math.cos( t ) );
  132. return point.set( x, y, z );
  133. }
  134. }
  135. /**
  136. * A helix curve.
  137. *
  138. * @augments Curve
  139. */
  140. class HelixCurve extends Curve {
  141. /**
  142. * This method returns a vector in 3D space for the given interpolation factor.
  143. *
  144. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  145. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  146. * @return {Vector3} The position on the curve.
  147. */
  148. getPoint( t, optionalTarget = new Vector3() ) {
  149. const point = optionalTarget;
  150. const a = 30; // radius
  151. const b = 150; // height
  152. const t2 = 2 * Math.PI * t * b / 30;
  153. const x = Math.cos( t2 ) * a;
  154. const y = Math.sin( t2 ) * a;
  155. const z = b * t;
  156. return point.set( x, y, z );
  157. }
  158. }
  159. /**
  160. * A Trefoil Knot.
  161. *
  162. * @augments Curve
  163. */
  164. class TrefoilKnot extends Curve {
  165. /**
  166. * Constructs a new Trefoil Knot.
  167. *
  168. * @param {number} [scale=10] - The curve's scale.
  169. */
  170. constructor( scale = 10 ) {
  171. super();
  172. /**
  173. * The curve's scale.
  174. *
  175. * @type {number}
  176. * @default 10
  177. */
  178. this.scale = scale;
  179. }
  180. /**
  181. * This method returns a vector in 3D space for the given interpolation factor.
  182. *
  183. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  184. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  185. * @return {Vector3} The position on the curve.
  186. */
  187. getPoint( t, optionalTarget = new Vector3() ) {
  188. const point = optionalTarget;
  189. t *= Math.PI * 2;
  190. const x = ( 2 + Math.cos( 3 * t ) ) * Math.cos( 2 * t );
  191. const y = ( 2 + Math.cos( 3 * t ) ) * Math.sin( 2 * t );
  192. const z = Math.sin( 3 * t );
  193. return point.set( x, y, z ).multiplyScalar( this.scale );
  194. }
  195. }
  196. /**
  197. * A torus knot.
  198. *
  199. * @augments Curve
  200. */
  201. class TorusKnot extends Curve {
  202. /**
  203. * Constructs a new torus knot.
  204. *
  205. * @param {number} [scale=10] - The curve's scale.
  206. */
  207. constructor( scale = 10 ) {
  208. super();
  209. /**
  210. * The curve's scale.
  211. *
  212. * @type {number}
  213. * @default 10
  214. */
  215. this.scale = scale;
  216. }
  217. /**
  218. * This method returns a vector in 3D space for the given interpolation factor.
  219. *
  220. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  221. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  222. * @return {Vector3} The position on the curve.
  223. */
  224. getPoint( t, optionalTarget = new Vector3() ) {
  225. const point = optionalTarget;
  226. const p = 3;
  227. const q = 4;
  228. t *= Math.PI * 2;
  229. const x = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t );
  230. const y = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t );
  231. const z = Math.sin( q * t );
  232. return point.set( x, y, z ).multiplyScalar( this.scale );
  233. }
  234. }
  235. /**
  236. * A Cinquefoil Knot.
  237. *
  238. * @augments Curve
  239. */
  240. class CinquefoilKnot extends Curve {
  241. /**
  242. * Constructs a new Cinquefoil Knot.
  243. *
  244. * @param {number} [scale=10] - The curve's scale.
  245. */
  246. constructor( scale = 10 ) {
  247. super();
  248. /**
  249. * The curve's scale.
  250. *
  251. * @type {number}
  252. * @default 10
  253. */
  254. this.scale = scale;
  255. }
  256. /**
  257. * This method returns a vector in 3D space for the given interpolation factor.
  258. *
  259. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  260. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  261. * @return {Vector3} The position on the curve.
  262. */
  263. getPoint( t, optionalTarget = new Vector3() ) {
  264. const point = optionalTarget;
  265. const p = 2;
  266. const q = 5;
  267. t *= Math.PI * 2;
  268. const x = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t );
  269. const y = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t );
  270. const z = Math.sin( q * t );
  271. return point.set( x, y, z ).multiplyScalar( this.scale );
  272. }
  273. }
  274. /**
  275. * A Trefoil Polynomial Knot.
  276. *
  277. * @augments Curve
  278. */
  279. class TrefoilPolynomialKnot extends Curve {
  280. /**
  281. * Constructs a new Trefoil Polynomial Knot.
  282. *
  283. * @param {number} [scale=10] - The curve's scale.
  284. */
  285. constructor( scale = 10 ) {
  286. super();
  287. /**
  288. * The curve's scale.
  289. *
  290. * @type {number}
  291. * @default 10
  292. */
  293. this.scale = scale;
  294. }
  295. /**
  296. * This method returns a vector in 3D space for the given interpolation factor.
  297. *
  298. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  299. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  300. * @return {Vector3} The position on the curve.
  301. */
  302. getPoint( t, optionalTarget = new Vector3() ) {
  303. const point = optionalTarget;
  304. t = t * 4 - 2;
  305. const x = Math.pow( t, 3 ) - 3 * t;
  306. const y = Math.pow( t, 4 ) - 4 * t * t;
  307. const z = 1 / 5 * Math.pow( t, 5 ) - 2 * t;
  308. return point.set( x, y, z ).multiplyScalar( this.scale );
  309. }
  310. }
  311. function scaleTo( x, y, t ) {
  312. const r = y - x;
  313. return t * r + x;
  314. }
  315. /**
  316. * A Figure Eight Polynomial Knot.
  317. *
  318. * @augments Curve
  319. */
  320. class FigureEightPolynomialKnot extends Curve {
  321. /**
  322. * Constructs a new Figure Eight Polynomial Knot.
  323. *
  324. * @param {number} [scale=1] - The curve's scale.
  325. */
  326. constructor( scale = 1 ) {
  327. super();
  328. /**
  329. * The curve's scale.
  330. *
  331. * @type {number}
  332. * @default 1
  333. */
  334. this.scale = scale;
  335. }
  336. /**
  337. * This method returns a vector in 3D space for the given interpolation factor.
  338. *
  339. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  340. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  341. * @return {Vector3} The position on the curve.
  342. */
  343. getPoint( t, optionalTarget = new Vector3() ) {
  344. const point = optionalTarget;
  345. t = scaleTo( - 4, 4, t );
  346. const x = 2 / 5 * t * ( t * t - 7 ) * ( t * t - 10 );
  347. const y = Math.pow( t, 4 ) - 13 * t * t;
  348. const z = 1 / 10 * t * ( t * t - 4 ) * ( t * t - 9 ) * ( t * t - 12 );
  349. return point.set( x, y, z ).multiplyScalar( this.scale );
  350. }
  351. }
  352. /**
  353. * A Decorated Torus Knot 4a.
  354. *
  355. * @augments Curve
  356. */
  357. class DecoratedTorusKnot4a extends Curve {
  358. /**
  359. * Constructs a new Decorated Torus Knot 4a.
  360. *
  361. * @param {number} [scale=1] - The curve's scale.
  362. */
  363. constructor( scale = 40 ) {
  364. super();
  365. /**
  366. * The curve's scale.
  367. *
  368. * @type {number}
  369. * @default 40
  370. */
  371. this.scale = scale;
  372. }
  373. /**
  374. * This method returns a vector in 3D space for the given interpolation factor.
  375. *
  376. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  377. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  378. * @return {Vector3} The position on the curve.
  379. */
  380. getPoint( t, optionalTarget = new Vector3() ) {
  381. const point = optionalTarget;
  382. t *= Math.PI * 2;
  383. const x = Math.cos( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) );
  384. const y = Math.sin( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) );
  385. const z = 0.35 * Math.sin( 5 * t );
  386. return point.set( x, y, z ).multiplyScalar( this.scale );
  387. }
  388. }
  389. /**
  390. * A Decorated Torus Knot 4b.
  391. *
  392. * @augments Curve
  393. */
  394. class DecoratedTorusKnot4b extends Curve {
  395. /**
  396. * Constructs a new Decorated Torus Knot 4b.
  397. *
  398. * @param {number} [scale=1] - The curve's scale.
  399. */
  400. constructor( scale = 40 ) {
  401. super();
  402. /**
  403. * The curve's scale.
  404. *
  405. * @type {number}
  406. * @default 40
  407. */
  408. this.scale = scale;
  409. }
  410. /**
  411. * This method returns a vector in 3D space for the given interpolation factor.
  412. *
  413. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  414. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  415. * @return {Vector3} The position on the curve.
  416. */
  417. getPoint( t, optionalTarget = new Vector3() ) {
  418. const point = optionalTarget;
  419. const fi = t * Math.PI * 2;
  420. const x = Math.cos( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) );
  421. const y = Math.sin( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) );
  422. const z = 0.2 * Math.sin( 9 * fi );
  423. return point.set( x, y, z ).multiplyScalar( this.scale );
  424. }
  425. }
  426. /**
  427. * A Decorated Torus Knot 5a.
  428. *
  429. * @augments Curve
  430. */
  431. class DecoratedTorusKnot5a extends Curve {
  432. /**
  433. * Constructs a new Decorated Torus Knot 5a.
  434. *
  435. * @param {number} [scale=1] - The curve's scale.
  436. */
  437. constructor( scale = 40 ) {
  438. super();
  439. /**
  440. * The curve's scale.
  441. *
  442. * @type {number}
  443. * @default 40
  444. */
  445. this.scale = scale;
  446. }
  447. /**
  448. * This method returns a vector in 3D space for the given interpolation factor.
  449. *
  450. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  451. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  452. * @return {Vector3} The position on the curve.
  453. */
  454. getPoint( t, optionalTarget = new Vector3() ) {
  455. const point = optionalTarget;
  456. const fi = t * Math.PI * 2;
  457. const x = Math.cos( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) );
  458. const y = Math.sin( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) );
  459. const z = 0.2 * Math.sin( 20 * fi );
  460. return point.set( x, y, z ).multiplyScalar( this.scale );
  461. }
  462. }
  463. /**
  464. * A Decorated Torus Knot 5c.
  465. *
  466. * @augments Curve
  467. */
  468. class DecoratedTorusKnot5c extends Curve {
  469. /**
  470. * Constructs a new Decorated Torus Knot 5c.
  471. *
  472. * @param {number} [scale=1] - The curve's scale.
  473. */
  474. constructor( scale = 40 ) {
  475. super();
  476. /**
  477. * The curve's scale.
  478. *
  479. * @type {number}
  480. * @default 40
  481. */
  482. this.scale = scale;
  483. }
  484. /**
  485. * This method returns a vector in 3D space for the given interpolation factor.
  486. *
  487. * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
  488. * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
  489. * @return {Vector3} The position on the curve.
  490. */
  491. getPoint( t, optionalTarget = new Vector3() ) {
  492. const point = optionalTarget;
  493. const fi = t * Math.PI * 2;
  494. const x = Math.cos( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) );
  495. const y = Math.sin( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) );
  496. const z = 0.35 * Math.sin( 15 * fi );
  497. return point.set( x, y, z ).multiplyScalar( this.scale );
  498. }
  499. }
  500. export {
  501. GrannyKnot,
  502. HeartCurve,
  503. VivianiCurve,
  504. KnotCurve,
  505. HelixCurve,
  506. TrefoilKnot,
  507. TorusKnot,
  508. CinquefoilKnot,
  509. TrefoilPolynomialKnot,
  510. FigureEightPolynomialKnot,
  511. DecoratedTorusKnot4a,
  512. DecoratedTorusKnot4b,
  513. DecoratedTorusKnot5a,
  514. DecoratedTorusKnot5c
  515. };
粤ICP备19079148号