modeling/src/operations/transforms/center.js

  1. const flatten = require('../../utils/flatten')
  2. const geom2 = require('../../geometries/geom2')
  3. const geom3 = require('../../geometries/geom3')
  4. const path2 = require('../../geometries/path2')
  5. const measureBoundingBox = require('../../measurements/measureBoundingBox')
  6. const { translate } = require('./translate')
  7. const centerGeometry = (options, object) => {
  8. const defaults = {
  9. axes: [true, true, true],
  10. relativeTo: [0, 0, 0]
  11. }
  12. const { axes, relativeTo } = Object.assign({}, defaults, options)
  13. const bounds = measureBoundingBox(object)
  14. const offset = [0, 0, 0]
  15. if (axes[0]) offset[0] = relativeTo[0] - (bounds[0][0] + ((bounds[1][0] - bounds[0][0]) / 2))
  16. if (axes[1]) offset[1] = relativeTo[1] - (bounds[0][1] + ((bounds[1][1] - bounds[0][1]) / 2))
  17. if (axes[2]) offset[2] = relativeTo[2] - (bounds[0][2] + ((bounds[1][2] - bounds[0][2]) / 2))
  18. return translate(offset, object)
  19. }
  20. /**
  21. * Center the given objects using the given options.
  22. * @param {Object} options - options for centering
  23. * @param {Array} [options.axes=[true,true,true]] - axis of which to center, true or false
  24. * @param {Array} [options.relativeTo=[0,0,0]] - relative point of which to center the objects
  25. * @param {...Object} objects - the objects to center
  26. * @return {Object|Array} the centered object, or a list of centered objects
  27. * @alias module:modeling/transforms.center
  28. *
  29. * @example
  30. * let myshape = center({axes: [true,false,false]}, sphere()) // center about the X axis
  31. */
  32. const center = (options, ...objects) => {
  33. const defaults = {
  34. axes: [true, true, true],
  35. relativeTo: [0, 0, 0]
  36. // TODO: Add additional 'methods' of centering: midpoint, centroid
  37. }
  38. const { axes, relativeTo } = Object.assign({}, defaults, options)
  39. objects = flatten(objects)
  40. if (objects.length === 0) throw new Error('wrong number of arguments')
  41. if (relativeTo.length !== 3) throw new Error('relativeTo must be an array of length 3')
  42. options = { axes, relativeTo }
  43. const results = objects.map((object) => {
  44. if (path2.isA(object)) return centerGeometry(options, object)
  45. if (geom2.isA(object)) return centerGeometry(options, object)
  46. if (geom3.isA(object)) return centerGeometry(options, object)
  47. return object
  48. })
  49. return results.length === 1 ? results[0] : results
  50. }
  51. /**
  52. * Center the given objects about the X axis.
  53. * @param {...Object} objects - the objects to center
  54. * @return {Object|Array} the centered object, or a list of centered objects
  55. * @alias module:modeling/transforms.centerX
  56. */
  57. const centerX = (...objects) => center({ axes: [true, false, false] }, objects)
  58. /**
  59. * Center the given objects about the Y axis.
  60. * @param {...Object} objects - the objects to center
  61. * @return {Object|Array} the centered object, or a list of centered objects
  62. * @alias module:modeling/transforms.centerY
  63. */
  64. const centerY = (...objects) => center({ axes: [false, true, false] }, objects)
  65. /**
  66. * Center the given objects about the Z axis.
  67. * @param {...Object} objects - the objects to center
  68. * @return {Object|Array} the centered object, or a list of centered objects
  69. * @alias module:modeling/transforms.centerZ
  70. */
  71. const centerZ = (...objects) => center({ axes: [false, false, true] }, objects)
  72. module.exports = {
  73. center,
  74. centerX,
  75. centerY,
  76. centerZ
  77. }