modeling/src/operations/transforms/mirror.js

  1. const flatten = require('../../utils/flatten')
  2. const mat4 = require('../../maths/mat4')
  3. const plane = require('../../maths/plane')
  4. const geom2 = require('../../geometries/geom2')
  5. const geom3 = require('../../geometries/geom3')
  6. const path2 = require('../../geometries/path2')
  7. /**
  8. * Mirror the given objects using the given options.
  9. * @param {Object} options - options for mirror
  10. * @param {Array} [options.origin=[0,0,0]] - the origin of the plane
  11. * @param {Array} [options.normal=[0,0,1]] - the normal vector of the plane
  12. * @param {...Object} objects - the objects to mirror
  13. * @return {Object|Array} the mirrored object, or a list of mirrored objects
  14. * @alias module:modeling/transforms.mirror
  15. *
  16. * @example
  17. * let myshape = mirror({normal: [0,0,10]}, cube({center: [0,0,15], radius: [20, 25, 5]}))
  18. */
  19. const mirror = (options, ...objects) => {
  20. const defaults = {
  21. origin: [0, 0, 0],
  22. normal: [0, 0, 1] // Z axis
  23. }
  24. const { origin, normal } = Object.assign({}, defaults, options)
  25. objects = flatten(objects)
  26. if (objects.length === 0) throw new Error('wrong number of arguments')
  27. const planeOfMirror = plane.fromNormalAndPoint(plane.create(), normal, origin)
  28. // verify the plane, i.e. check that the given normal was valid
  29. if (Number.isNaN(planeOfMirror[0])) {
  30. throw new Error('the given origin and normal do not define a proper plane')
  31. }
  32. const matrix = mat4.mirrorByPlane(mat4.create(), planeOfMirror)
  33. const results = objects.map((object) => {
  34. if (path2.isA(object)) return path2.transform(matrix, object)
  35. if (geom2.isA(object)) return geom2.transform(matrix, object)
  36. if (geom3.isA(object)) return geom3.transform(matrix, object)
  37. return object
  38. })
  39. return results.length === 1 ? results[0] : results
  40. }
  41. /**
  42. * Mirror the given objects about the X axis.
  43. * @param {...Object} objects - the objects to mirror
  44. * @return {Object|Array} the mirrored object, or a list of mirrored objects
  45. * @alias module:modeling/transforms.mirrorX
  46. */
  47. const mirrorX = (...objects) => mirror({ normal: [1, 0, 0] }, objects)
  48. /**
  49. * Mirror the given objects about the Y axis.
  50. * @param {...Object} objects - the geometries to mirror
  51. * @return {Object|Array} the mirrored object, or a list of mirrored objects
  52. * @alias module:modeling/transforms.mirrorY
  53. */
  54. const mirrorY = (...objects) => mirror({ normal: [0, 1, 0] }, objects)
  55. /**
  56. * Mirror the given objects about the Z axis.
  57. * @param {...Object} objects - the geometries to mirror
  58. * @return {Object|Array} the mirrored object, or a list of mirrored objects
  59. * @alias module:modeling/transforms.mirrorZ
  60. */
  61. const mirrorZ = (...objects) => mirror({ normal: [0, 0, 1] }, objects)
  62. module.exports = {
  63. mirror,
  64. mirrorX,
  65. mirrorY,
  66. mirrorZ
  67. }