@jscad/modeling 2.12.3 → 2.12.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/LICENSE +1 -1
- package/dist/jscad-modeling.min.js +3 -3
- package/package.json +2 -2
- package/src/curves/index.js +0 -1
- package/src/geometries/geom3/fromPointsConvex.test.js +20 -15
- package/src/maths/OrthoNormalBasis.js +0 -148
- package/src/maths/index.js +1 -2
- package/src/operations/booleans/intersect.js +1 -1
- package/src/operations/booleans/scission.js +2 -0
- package/src/operations/booleans/subtract.js +1 -1
- package/src/operations/booleans/union.js +1 -1
- package/src/operations/expansions/expand.js +1 -1
- package/src/operations/extrusions/extrudeHelical.js +2 -8
- package/src/operations/extrusions/index.js +1 -1
- package/src/operations/hulls/index.js +1 -1
- package/src/operations/modifiers/index.js +1 -1
- package/src/operations/modifiers/snap.js +1 -1
- package/src/primitives/arc.js +2 -0
- package/src/primitives/polygon.js +2 -2
- package/src/primitives/polygon.test.js +1 -1
- package/src/primitives/polyhedron.js +2 -1
- package/src/primitives/torus.js +1 -1
- package/src/text/vectorChar.js +0 -3
- package/src/text/vectorText.js +0 -3
- package/src/utils/index.js +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [2.12.5](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/modeling@2.12.4...@jscad/modeling@2.12.5) (2024-12-29)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @jscad/modeling
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [2.12.4](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/modeling@2.12.3...@jscad/modeling@2.12.4) (2024-11-10)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @jscad/modeling
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
## [2.12.3](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/modeling@2.12.2...@jscad/modeling@2.12.3) (2024-10-06)
|
|
7
23
|
|
|
8
24
|
|
package/LICENSE
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
The MIT License (MIT)
|
|
3
3
|
|
|
4
|
-
Copyright (c) 2017-
|
|
4
|
+
Copyright (c) 2017-2024 JSCAD Organization
|
|
5
5
|
|
|
6
6
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -275,7 +275,7 @@ const signedDistanceToPoint=require("../../maths/plane/signedDistanceToPoint"),{
|
|
|
275
275
|
module.exports={colors:require("./colors"),curves:require("./curves"),geometries:require("./geometries"),maths:require("./maths"),measurements:require("./measurements"),primitives:require("./primitives"),text:require("./text"),utils:require("./utils"),booleans:require("./operations/booleans"),expansions:require("./operations/expansions"),extrusions:require("./operations/extrusions"),hulls:require("./operations/hulls"),modifiers:require("./operations/modifiers"),transforms:require("./operations/transforms")};
|
|
276
276
|
|
|
277
277
|
},{"./colors":8,"./curves":19,"./geometries":50,"./maths":95,"./measurements":252,"./operations/booleans":266,"./operations/expansions":295,"./operations/extrusions":318,"./operations/hulls":341,"./operations/modifiers":352,"./operations/transforms":362,"./primitives":378,"./text":392,"./utils":400}],93:[function(require,module,exports){
|
|
278
|
-
const mat4=require("./mat4"),vec2=require("./vec2"),vec3=require("./vec3"),OrthoNormalBasis=function(e,t){arguments.length<2&&(t=vec3.orthogonal(vec3.create(),e)),this.v=vec3.normalize(vec3.create(),vec3.cross(vec3.create(),e,t)),this.u=vec3.cross(vec3.create(),this.v,e),this.plane=e,this.planeorigin=vec3.scale(vec3.create(),e,e[3])};OrthoNormalBasis.
|
|
278
|
+
const mat4=require("./mat4"),vec2=require("./vec2"),vec3=require("./vec3"),OrthoNormalBasis=function(e,t){arguments.length<2&&(t=vec3.orthogonal(vec3.create(),e)),this.v=vec3.normalize(vec3.create(),vec3.cross(vec3.create(),e,t)),this.u=vec3.cross(vec3.create(),this.v,e),this.plane=e,this.planeorigin=vec3.scale(vec3.create(),e,e[3])};OrthoNormalBasis.prototype={getProjectionMatrix:function(){return mat4.fromValues(this.u[0],this.v[0],this.plane[0],0,this.u[1],this.v[1],this.plane[1],0,this.u[2],this.v[2],this.plane[2],0,0,0,-this.plane[3],1)},getInverseProjectionMatrix:function(){const e=vec3.scale(vec3.create(),this.plane,this.plane[3]);return mat4.fromValues(this.u[0],this.u[1],this.u[2],0,this.v[0],this.v[1],this.v[2],0,this.plane[0],this.plane[1],this.plane[2],0,e[0],e[1],e[2],1)},to2D:function(e){return vec2.fromValues(vec3.dot(e,this.u),vec3.dot(e,this.v))},to3D:function(e){const t=vec3.scale(vec3.create(),this.u,e[0]),s=vec3.scale(vec3.create(),this.v,e[1]),i=vec3.add(t,t,this.planeorigin);return vec3.add(s,s,i)}},module.exports=OrthoNormalBasis;
|
|
279
279
|
|
|
280
280
|
},{"./mat4":143,"./vec2":191,"./vec3":222}],94:[function(require,module,exports){
|
|
281
281
|
const spatialResolution=1e5,EPS=1e-5,NEPS=1e-13,TAU=2*Math.PI;module.exports={EPS:EPS,NEPS:NEPS,TAU:TAU,spatialResolution:1e5};
|
|
@@ -1136,7 +1136,7 @@ module.exports={arc:require("./arc"),circle:require("./circle"),cube:require("./
|
|
|
1136
1136
|
const path2=require("../geometries/path2"),line=r=>{if(!Array.isArray(r))throw new Error("points must be an array");return path2.fromPoints({},r)};module.exports=line;
|
|
1137
1137
|
|
|
1138
1138
|
},{"../geometries/path2":62}],380:[function(require,module,exports){
|
|
1139
|
-
const geom2=require("../geometries/geom2"),polygon=r=>{const{points:o,paths:t,orientation:e}=Object.assign({},{points:[],paths:[],orientation:"counterclockwise"},r);if(!Array.isArray(o)||!Array.isArray(t))throw new Error("points and paths must be arrays");let s=o;Array.isArray(o[0])&&(Array.isArray(o[0][0])||(s=[o])),s.forEach((r,o)=>{if(!Array.isArray(r))throw new Error("list of points "+o+" must be an array");if(r.length<3)throw new Error("list of points "+o+" must contain three or more points");r.forEach((r,t)=>{if(!Array.isArray(r))throw new Error("list of points "+o+", point "+t+" must be an array");if(r.length<2)throw new Error("list of points "+o+", point "+t+" must contain by X and Y values")})});let a=t;if(0===t.length){let r=0;a=s.map(o=>o.map(o=>r++))}const n=[];s.forEach(r=>r.forEach(r=>n.push(r)));let i=[];a.forEach(r=>{const o=r.map(r=>n[r]),t=geom2.fromPoints(o);i=i.concat(geom2.toSides(t))});let c=geom2.create(i);return"clockwise"
|
|
1139
|
+
const geom2=require("../geometries/geom2"),polygon=r=>{const{points:o,paths:t,orientation:e}=Object.assign({},{points:[],paths:[],orientation:"counterclockwise"},r);if(!Array.isArray(o)||!Array.isArray(t))throw new Error("points and paths must be arrays");let s=o;Array.isArray(o[0])&&(Array.isArray(o[0][0])||(s=[o])),s.forEach((r,o)=>{if(!Array.isArray(r))throw new Error("list of points "+o+" must be an array");if(r.length<3)throw new Error("list of points "+o+" must contain three or more points");r.forEach((r,t)=>{if(!Array.isArray(r))throw new Error("list of points "+o+", point "+t+" must be an array");if(r.length<2)throw new Error("list of points "+o+", point "+t+" must contain by X and Y values")})});let a=t;if(0===t.length){let r=0;a=s.map(o=>o.map(o=>r++))}const n=[];s.forEach(r=>r.forEach(r=>n.push(r)));let i=[];a.forEach(r=>{const o=r.map(r=>n[r]),t=geom2.fromPoints(o);i=i.concat(geom2.toSides(t))});let c=geom2.create(i);return"clockwise"===e&&(c=geom2.reverse(c)),c};module.exports=polygon;
|
|
1140
1140
|
|
|
1141
1141
|
},{"../geometries/geom2":25}],381:[function(require,module,exports){
|
|
1142
1142
|
const geom3=require("../geometries/geom3"),poly3=require("../geometries/poly3"),{isNumberArray:isNumberArray}=require("./commonChecks"),polyhedron=r=>{const e={points:[],faces:[],colors:void 0,orientation:"outward"},{points:o,faces:a,colors:t,orientation:n}=Object.assign({},e,r);if(!Array.isArray(o)||!Array.isArray(a))throw new Error("points and faces must be arrays");if(o.length<3)throw new Error("three or more points are required");if(a.length<1)throw new Error("one or more faces are required");if(t){if(!Array.isArray(t))throw new Error("colors must be an array");if(t.length!==a.length)throw new Error("faces and colors must have the same length")}o.forEach((r,e)=>{if(!isNumberArray(r,3))throw new Error(`point ${e} must be an array of X, Y, Z values`)}),a.forEach((r,e)=>{if(r.length<3)throw new Error(`face ${e} must contain 3 or more indexes`);if(!isNumberArray(r,r.length))throw new Error(`face ${e} must be an array of numbers`)}),"outward"!==n&&a.forEach(r=>r.reverse());const s=a.map((r,e)=>{const a=poly3.create(r.map(r=>o[r]));return t&&t[e]&&(a.color=t[e]),a});return geom3.create(s)};module.exports=polyhedron;
|
|
@@ -1163,7 +1163,7 @@ const rectangle=require("./rectangle"),{isGTE:isGTE}=require("./commonChecks"),s
|
|
|
1163
1163
|
const{TAU:TAU}=require("../maths/constants"),vec2=require("../maths/vec2"),geom2=require("../geometries/geom2"),{isGT:isGT,isGTE:isGTE,isNumberArray:isNumberArray}=require("./commonChecks"),getRadiusRatio=(e,r)=>e>0&&r>1&&r<e/2?Math.cos(Math.PI*r/e)/Math.cos(Math.PI*(r-1)/e):0,getPoints=(e,r,t,s)=>{const o=TAU/e,i=[];for(let a=0;a<e;a++){const e=vec2.fromAngleRadians(vec2.create(),o*a+t);vec2.scale(e,e,r),vec2.add(e,s,e),i.push(e)}return i},star=e=>{let{center:r,vertices:t,outerRadius:s,innerRadius:o,density:i,startAngle:a}=Object.assign({},{center:[0,0],vertices:5,outerRadius:1,innerRadius:0,density:2,startAngle:0},e);if(!isNumberArray(r,2))throw new Error("center must be an array of X and Y values");if(!isGTE(t,2))throw new Error("vertices must be two or more");if(!isGT(s,0))throw new Error("outerRadius must be greater than zero");if(!isGTE(o,0))throw new Error("innerRadius must be greater than zero");if(!isGTE(a,0))throw new Error("startAngle must be greater than zero");if(t=Math.floor(t),i=Math.floor(i),a%=TAU,0===o){if(!isGTE(i,2))throw new Error("density must be two or more");o=s*getRadiusRatio(t,i)}const n=vec2.clone(r),u=getPoints(t,s,a,n),c=getPoints(t,o,a+Math.PI/t,n),h=[];for(let e=0;e<t;e++)h.push(u[e]),h.push(c[e]);return geom2.fromPoints(h)};module.exports=star;
|
|
1164
1164
|
|
|
1165
1165
|
},{"../geometries/geom2":25,"../maths/constants":94,"../maths/vec2":191,"./commonChecks":370}],389:[function(require,module,exports){
|
|
1166
|
-
const{TAU:TAU}=require("../maths/constants"),extrudeRotate=require("../operations/extrusions/extrudeRotate"),{rotate:rotate}=require("../operations/transforms/rotate"),{translate:translate}=require("../operations/transforms/translate"),circle=require("./circle"),{isGT:isGT,isGTE:isGTE}=require("./commonChecks"),torus=e=>{const r={innerRadius:1,innerSegments:32,outerRadius:4,outerSegments:32,innerRotation:0,startAngle:0,outerRotation:TAU},{innerRadius:t,innerSegments:o,outerRadius:n,outerSegments:s,innerRotation:i,startAngle:a,outerRotation:u}=Object.assign({},r,e);if(!isGT(t,0))throw new Error("innerRadius must be greater than zero");if(!isGTE(o,3))throw new Error("innerSegments must be three or more");if(!isGT(n,0))throw new Error("outerRadius must be greater than zero");if(!isGTE(s,3))throw new Error("outerSegments must be three or more");if(!isGTE(a,0))throw new Error("startAngle must be positive");if(!isGT(u,0))throw new Error("outerRotation must be greater than zero");if(t>=n)throw new Error("inner circle is
|
|
1166
|
+
const{TAU:TAU}=require("../maths/constants"),extrudeRotate=require("../operations/extrusions/extrudeRotate"),{rotate:rotate}=require("../operations/transforms/rotate"),{translate:translate}=require("../operations/transforms/translate"),circle=require("./circle"),{isGT:isGT,isGTE:isGTE}=require("./commonChecks"),torus=e=>{const r={innerRadius:1,innerSegments:32,outerRadius:4,outerSegments:32,innerRotation:0,startAngle:0,outerRotation:TAU},{innerRadius:t,innerSegments:o,outerRadius:n,outerSegments:s,innerRotation:i,startAngle:a,outerRotation:u}=Object.assign({},r,e);if(!isGT(t,0))throw new Error("innerRadius must be greater than zero");if(!isGTE(o,3))throw new Error("innerSegments must be three or more");if(!isGT(n,0))throw new Error("outerRadius must be greater than zero");if(!isGTE(s,3))throw new Error("outerSegments must be three or more");if(!isGTE(a,0))throw new Error("startAngle must be positive");if(!isGT(u,0))throw new Error("outerRotation must be greater than zero");if(t>=n)throw new Error("inner circle is too large to rotate about the outer circle");let m=circle({radius:t,segments:o});return 0!==i&&(m=rotate([0,0,i],m)),m=translate([n,0],m),extrudeRotate({startAngle:a,angle:u,segments:s},m)};module.exports=torus;
|
|
1167
1167
|
|
|
1168
1168
|
},{"../maths/constants":94,"../operations/extrusions/extrudeRotate":316,"../operations/transforms/rotate":364,"../operations/transforms/translate":367,"./circle":369,"./commonChecks":370}],390:[function(require,module,exports){
|
|
1169
1169
|
const{NEPS:NEPS}=require("../maths/constants"),vec2=require("../maths/vec2"),geom2=require("../geometries/geom2"),{isNumberArray:isNumberArray}=require("./commonChecks"),solveAngleFromSSS=(e,r,t)=>Math.acos((e*e+r*r-t*t)/(2*e*r)),solveSideFromSAS=(e,r,t)=>r>NEPS?Math.sqrt(e*e+t*t-2*e*t*Math.cos(r)):Math.sqrt((e-t)*(e-t)+e*t*r*r*(1-r*r/12)),solveAAA=e=>{if(Math.abs(e[0]+e[1]+e[2]-Math.PI)>NEPS)throw new Error("AAA triangles require angles that sum to PI");const r=e[0],t=e[1],s=Math.PI-r-t,a=1/Math.sin(s)*Math.sin(r),n=1/Math.sin(s)*Math.sin(t);return createTriangle(r,t,s,a,n,1)},solveAAS=e=>{const r=e[0],t=e[1],s=Math.PI+NEPS-r-t;if(s<NEPS)throw new Error("AAS triangles require angles that sum to PI");const a=e[2],n=a/Math.sin(r)*Math.sin(t),o=a/Math.sin(r)*Math.sin(s);return createTriangle(r,t,s,a,n,o)},solveASA=e=>{const r=e[0],t=e[2],s=Math.PI+NEPS-r-t;if(s<NEPS)throw new Error("ASA triangles require angles that sum to PI");const a=e[1],n=a/Math.sin(s)*Math.sin(r),o=a/Math.sin(s)*Math.sin(t);return createTriangle(r,t,s,n,o,a)},solveSAS=e=>{const r=e[0],t=e[1],s=e[2],a=solveSideFromSAS(r,t,s),n=solveAngleFromSSS(a,r,s),o=Math.PI-n-t;return createTriangle(n,t,o,s,a,r)},solveSSA=e=>{const r=e[0],t=e[1],s=e[2],a=Math.asin(t*Math.sin(s)/r),n=Math.PI-a-s,o=r/Math.sin(s)*Math.sin(n);return createTriangle(a,n,s,t,o,r)},solveSSS=e=>{const r=e[1],t=e[2],s=e[0];if(r+t<=s||t+s<=r||s+r<=t)throw new Error("SSS triangle is incorrect, as the longest side is longer than the sum of the other sides");const a=solveAngleFromSSS(t,s,r),n=solveAngleFromSSS(s,r,t),o=Math.PI-a-n;return createTriangle(a,n,o,r,t,s)},createTriangle=(e,r,t,s,a,n)=>{const o=vec2.fromValues(0,0),i=vec2.fromValues(n,0),S=vec2.fromValues(s,0);return vec2.add(S,vec2.rotate(S,S,[0,0],Math.PI-r),i),geom2.fromPoints([o,i,S])},triangle=e=>{let{type:r,values:t}=Object.assign({},{type:"SSS",values:[1,1,1]},e);if("string"!=typeof r)throw new Error("triangle type must be a string");if("A"!==(r=r.toUpperCase())[0]&&"S"!==r[0]||"A"!==r[1]&&"S"!==r[1]||"A"!==r[2]&&"S"!==r[2])throw new Error("triangle type must contain three letters; A or S");if(!isNumberArray(t,3))throw new Error("triangle values must contain three values");if(!t.every(e=>e>0))throw new Error("triangle values must be greater than zero");switch(r){case"AAA":return solveAAA(t);case"AAS":return solveAAS(t);case"ASA":return solveASA(t);case"SAS":return solveSAS(t);case"SSA":return solveSSA(t);case"SSS":return solveSSS(t);default:throw new Error("invalid triangle type, try again")}};module.exports=triangle;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jscad/modeling",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.5",
|
|
4
4
|
"description": "Constructive Solid Geometry (CSG) Library for JSCAD",
|
|
5
5
|
"homepage": "https://openjscad.xyz/",
|
|
6
6
|
"repository": "https://github.com/jscad/OpenJSCAD.org",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"nyc": "15.1.0",
|
|
62
62
|
"uglifyify": "5.0.2"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "d8010c4f1d70685404a510d604f8b6d5c362f93a"
|
|
65
65
|
}
|
package/src/curves/index.js
CHANGED
|
@@ -3,24 +3,29 @@ const test = require('ava')
|
|
|
3
3
|
const { fromPointsConvex, validate } = require('./index')
|
|
4
4
|
|
|
5
5
|
test('fromPointsConvex (uniquePoints)', (t) => {
|
|
6
|
-
|
|
7
|
-
for(x
|
|
8
|
-
for(y
|
|
9
|
-
|
|
10
|
-
if (x*x+y*y+z*z <= 96)
|
|
11
|
-
|
|
6
|
+
const out = []
|
|
7
|
+
for (let x = -9; x <= 9; ++x) {
|
|
8
|
+
for (let y = -9; y <= 9; ++y) {
|
|
9
|
+
for (let z = -9; z <= 9; ++z) {
|
|
10
|
+
if (x * x + y * y + z * z <= 96) out.push([x, y, z])
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
const obs = fromPointsConvex(out)
|
|
14
16
|
validate(obs)
|
|
17
|
+
|
|
15
18
|
t.is(obs.polygons.length, 170)
|
|
16
|
-
t.true(obs.polygons.every((f) => ([3,4,8,9].indexOf(f.vertices.length) !== -1)))
|
|
17
|
-
|
|
19
|
+
t.true(obs.polygons.every((f) => ([3, 4, 8, 9].indexOf(f.vertices.length) !== -1)))
|
|
20
|
+
|
|
21
|
+
const c = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
18
22
|
obs.polygons.forEach((f) => c[f.vertices.length]++)
|
|
19
|
-
t.is(c[3], 120)
|
|
20
|
-
t.is(c[4], 24)
|
|
21
|
-
t.is(c[8], 18)
|
|
22
|
-
t.is(c[9], 8)
|
|
23
|
-
|
|
23
|
+
t.is(c[3], 120)
|
|
24
|
+
t.is(c[4], 24)
|
|
25
|
+
t.is(c[8], 18)
|
|
26
|
+
t.is(c[9], 8)
|
|
27
|
+
|
|
28
|
+
let edges2 = 336 * 2
|
|
24
29
|
obs.polygons.forEach((f) => edges2 -= f.vertices.length)
|
|
25
|
-
t.is(edges2, 0)
|
|
30
|
+
t.is(edges2, 0)
|
|
26
31
|
})
|
|
@@ -21,128 +21,6 @@ const OrthoNormalBasis = function (plane, rightvector) {
|
|
|
21
21
|
this.planeorigin = vec3.scale(vec3.create(), plane, plane[3])
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
// Get an orthonormal basis for the standard XYZ planes.
|
|
25
|
-
// Parameters: the names of two 3D axes. The 2d x axis will map to the first given 3D axis, the 2d y
|
|
26
|
-
// axis will map to the second.
|
|
27
|
-
// Prepend the axis with a "-" to invert the direction of this axis.
|
|
28
|
-
// For example: OrthoNormalBasis.GetCartesian("-Y","Z")
|
|
29
|
-
// will return an orthonormal basis where the 2d X axis maps to the 3D inverted Y axis, and
|
|
30
|
-
// the 2d Y axis maps to the 3D Z axis.
|
|
31
|
-
OrthoNormalBasis.GetCartesian = function (xaxisid, yaxisid) {
|
|
32
|
-
const axisid = xaxisid + '/' + yaxisid
|
|
33
|
-
let planenormal, rightvector
|
|
34
|
-
if (axisid === 'X/Y') {
|
|
35
|
-
planenormal = [0, 0, 1]
|
|
36
|
-
rightvector = [1, 0, 0]
|
|
37
|
-
} else if (axisid === 'Y/-X') {
|
|
38
|
-
planenormal = [0, 0, 1]
|
|
39
|
-
rightvector = [0, 1, 0]
|
|
40
|
-
} else if (axisid === '-X/-Y') {
|
|
41
|
-
planenormal = [0, 0, 1]
|
|
42
|
-
rightvector = [-1, 0, 0]
|
|
43
|
-
} else if (axisid === '-Y/X') {
|
|
44
|
-
planenormal = [0, 0, 1]
|
|
45
|
-
rightvector = [0, -1, 0]
|
|
46
|
-
} else if (axisid === '-X/Y') {
|
|
47
|
-
planenormal = [0, 0, -1]
|
|
48
|
-
rightvector = [-1, 0, 0]
|
|
49
|
-
} else if (axisid === '-Y/-X') {
|
|
50
|
-
planenormal = [0, 0, -1]
|
|
51
|
-
rightvector = [0, -1, 0]
|
|
52
|
-
} else if (axisid === 'X/-Y') {
|
|
53
|
-
planenormal = [0, 0, -1]
|
|
54
|
-
rightvector = [1, 0, 0]
|
|
55
|
-
} else if (axisid === 'Y/X') {
|
|
56
|
-
planenormal = [0, 0, -1]
|
|
57
|
-
rightvector = [0, 1, 0]
|
|
58
|
-
} else if (axisid === 'X/Z') {
|
|
59
|
-
planenormal = [0, -1, 0]
|
|
60
|
-
rightvector = [1, 0, 0]
|
|
61
|
-
} else if (axisid === 'Z/-X') {
|
|
62
|
-
planenormal = [0, -1, 0]
|
|
63
|
-
rightvector = [0, 0, 1]
|
|
64
|
-
} else if (axisid === '-X/-Z') {
|
|
65
|
-
planenormal = [0, -1, 0]
|
|
66
|
-
rightvector = [-1, 0, 0]
|
|
67
|
-
} else if (axisid === '-Z/X') {
|
|
68
|
-
planenormal = [0, -1, 0]
|
|
69
|
-
rightvector = [0, 0, -1]
|
|
70
|
-
} else if (axisid === '-X/Z') {
|
|
71
|
-
planenormal = [0, 1, 0]
|
|
72
|
-
rightvector = [-1, 0, 0]
|
|
73
|
-
} else if (axisid === '-Z/-X') {
|
|
74
|
-
planenormal = [0, 1, 0]
|
|
75
|
-
rightvector = [0, 0, -1]
|
|
76
|
-
} else if (axisid === 'X/-Z') {
|
|
77
|
-
planenormal = [0, 1, 0]
|
|
78
|
-
rightvector = [1, 0, 0]
|
|
79
|
-
} else if (axisid === 'Z/X') {
|
|
80
|
-
planenormal = [0, 1, 0]
|
|
81
|
-
rightvector = [0, 0, 1]
|
|
82
|
-
} else if (axisid === 'Y/Z') {
|
|
83
|
-
planenormal = [1, 0, 0]
|
|
84
|
-
rightvector = [0, 1, 0]
|
|
85
|
-
} else if (axisid === 'Z/-Y') {
|
|
86
|
-
planenormal = [1, 0, 0]
|
|
87
|
-
rightvector = [0, 0, 1]
|
|
88
|
-
} else if (axisid === '-Y/-Z') {
|
|
89
|
-
planenormal = [1, 0, 0]
|
|
90
|
-
rightvector = [0, -1, 0]
|
|
91
|
-
} else if (axisid === '-Z/Y') {
|
|
92
|
-
planenormal = [1, 0, 0]
|
|
93
|
-
rightvector = [0, 0, -1]
|
|
94
|
-
} else if (axisid === '-Y/Z') {
|
|
95
|
-
planenormal = [-1, 0, 0]
|
|
96
|
-
rightvector = [0, -1, 0]
|
|
97
|
-
} else if (axisid === '-Z/-Y') {
|
|
98
|
-
planenormal = [-1, 0, 0]
|
|
99
|
-
rightvector = [0, 0, -1]
|
|
100
|
-
} else if (axisid === 'Y/-Z') {
|
|
101
|
-
planenormal = [-1, 0, 0]
|
|
102
|
-
rightvector = [0, 1, 0]
|
|
103
|
-
} else if (axisid === 'Z/Y') {
|
|
104
|
-
planenormal = [-1, 0, 0]
|
|
105
|
-
rightvector = [0, 0, 1]
|
|
106
|
-
} else {
|
|
107
|
-
throw new Error('OrthoNormalBasis.GetCartesian: invalid combination of axis identifiers. Should pass two string arguments from [X,Y,Z,-X,-Y,-Z], being two different axes.')
|
|
108
|
-
}
|
|
109
|
-
return new OrthoNormalBasis(new Plane(new Vector3D(planenormal), 0), new Vector3D(rightvector))
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/*
|
|
113
|
-
// test code for OrthoNormalBasis.GetCartesian()
|
|
114
|
-
OrthoNormalBasis.GetCartesian_Test=function() {
|
|
115
|
-
let axisnames=["X","Y","Z","-X","-Y","-Z"];
|
|
116
|
-
let axisvectors=[[1,0,0], [0,1,0], [0,0,1], [-1,0,0], [0,-1,0], [0,0,-1]];
|
|
117
|
-
for(let axis1=0; axis1 < 3; axis1++) {
|
|
118
|
-
for(let axis1inverted=0; axis1inverted < 2; axis1inverted++) {
|
|
119
|
-
let axis1name=axisnames[axis1+3*axis1inverted];
|
|
120
|
-
let axis1vector=axisvectors[axis1+3*axis1inverted];
|
|
121
|
-
for(let axis2=0; axis2 < 3; axis2++) {
|
|
122
|
-
if(axis2 != axis1) {
|
|
123
|
-
for(let axis2inverted=0; axis2inverted < 2; axis2inverted++) {
|
|
124
|
-
let axis2name=axisnames[axis2+3*axis2inverted];
|
|
125
|
-
let axis2vector=axisvectors[axis2+3*axis2inverted];
|
|
126
|
-
let orthobasis=OrthoNormalBasis.GetCartesian(axis1name, axis2name);
|
|
127
|
-
let test1=orthobasis.to3D(new Vector2D([1,0]));
|
|
128
|
-
let test2=orthobasis.to3D(new Vector2D([0,1]));
|
|
129
|
-
let expected1=new Vector3D(axis1vector);
|
|
130
|
-
let expected2=new Vector3D(axis2vector);
|
|
131
|
-
let d1=test1.distanceTo(expected1);
|
|
132
|
-
let d2=test2.distanceTo(expected2);
|
|
133
|
-
if( (d1 > 0.01) || (d2 > 0.01) ) {
|
|
134
|
-
throw new Error("Wrong!");
|
|
135
|
-
}}}}}}
|
|
136
|
-
throw new Error("OK");
|
|
137
|
-
};
|
|
138
|
-
*/
|
|
139
|
-
|
|
140
|
-
// The z=0 plane, with the 3D x and y vectors mapped to the 2D x and y vector
|
|
141
|
-
OrthoNormalBasis.Z0Plane = function () {
|
|
142
|
-
const plane = new Plane(new Vector3D([0, 0, 1]), 0)
|
|
143
|
-
return new OrthoNormalBasis(plane, new Vector3D([1, 0, 0]))
|
|
144
|
-
}
|
|
145
|
-
|
|
146
24
|
OrthoNormalBasis.prototype = {
|
|
147
25
|
|
|
148
26
|
getProjectionMatrix: function () {
|
|
@@ -175,32 +53,6 @@ OrthoNormalBasis.prototype = {
|
|
|
175
53
|
const v3 = vec3.add(v1, v1, this.planeorigin)
|
|
176
54
|
const v4 = vec3.add(v2, v2, v3)
|
|
177
55
|
return v4
|
|
178
|
-
},
|
|
179
|
-
|
|
180
|
-
line3Dto2D: function (line3d) {
|
|
181
|
-
const a = line3d.point
|
|
182
|
-
const b = line3d.direction.plus(a)
|
|
183
|
-
const a2d = this.to2D(a)
|
|
184
|
-
const b2d = this.to2D(b)
|
|
185
|
-
return Line2D.fromPoints(a2d, b2d)
|
|
186
|
-
},
|
|
187
|
-
|
|
188
|
-
line2Dto3D: function (line2d) {
|
|
189
|
-
const a = line2d.origin()
|
|
190
|
-
const b = line2d.direction().plus(a)
|
|
191
|
-
const a3d = this.to3D(a)
|
|
192
|
-
const b3d = this.to3D(b)
|
|
193
|
-
return Line3D.fromPoints(a3d, b3d)
|
|
194
|
-
},
|
|
195
|
-
|
|
196
|
-
transform: function (matrix4x4) {
|
|
197
|
-
// todo: this may not work properly in case of mirroring
|
|
198
|
-
const newplane = this.plane.transform(matrix4x4)
|
|
199
|
-
const rightpointTransformed = this.u.transform(matrix4x4)
|
|
200
|
-
const originTransformed = new Vector3D(0, 0, 0).transform(matrix4x4)
|
|
201
|
-
const newrighthandvector = rightpointTransformed.minus(originTransformed)
|
|
202
|
-
const newbasis = new OrthoNormalBasis(newplane, newrighthandvector)
|
|
203
|
-
return newbasis
|
|
204
56
|
}
|
|
205
57
|
}
|
|
206
58
|
|
package/src/maths/index.js
CHANGED
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
* @see Most computations are based upon the glMatrix library (glmatrix.net)
|
|
5
5
|
* @module modeling/maths
|
|
6
6
|
* @example
|
|
7
|
-
* const { constants, line2, mat4, vec2, vec3 } = require('@jscad/modeling').maths
|
|
8
|
-
|
|
7
|
+
* const { constants, line2, line3, mat4, plane, utils, vec2, vec3, vec4 } = require('@jscad/modeling').maths
|
|
9
8
|
*/
|
|
10
9
|
module.exports = {
|
|
11
10
|
constants: require('./constants'),
|
|
@@ -17,7 +17,7 @@ const intersectGeom3 = require('./intersectGeom3')
|
|
|
17
17
|
* @alias module:modeling/booleans.intersect
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
|
-
* let myshape = intersect(cube({size:
|
|
20
|
+
* let myshape = intersect(cube({size: 5}), cube({size: 5, center: [3,3,3]}))
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* +-------+
|
|
@@ -9,6 +9,8 @@ const scissionGeom3 = require('./scissionGeom3')
|
|
|
9
9
|
/**
|
|
10
10
|
* Scission (divide) the given geometry into the component pieces.
|
|
11
11
|
*
|
|
12
|
+
* NOTE: Currently only 3D geometries are supported.
|
|
13
|
+
*
|
|
12
14
|
* @param {...Object} objects - list of geometries
|
|
13
15
|
* @returns {Array} list of pieces from each geometry
|
|
14
16
|
* @alias module:modeling/booleans.scission
|
|
@@ -17,7 +17,7 @@ const subtractGeom3 = require('./subtractGeom3')
|
|
|
17
17
|
* @alias module:modeling/booleans.subtract
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
|
-
* let myshape = subtract(cuboid({size:
|
|
20
|
+
* let myshape = subtract(cuboid({size: 5}), cuboid({size: 5, center: [3,3,3]}))
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* +-------+ +-------+
|
|
@@ -16,7 +16,7 @@ const unionGeom3 = require('./unionGeom3')
|
|
|
16
16
|
* @alias module:modeling/booleans.union
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
|
-
* let myshape = union(cube({size:
|
|
19
|
+
* let myshape = union(cube({size: 5}), cube({size: 5, center: [3,3,3]}))
|
|
20
20
|
*
|
|
21
21
|
* @example
|
|
22
22
|
* +-------+ +-------+
|
|
@@ -24,7 +24,7 @@ const expandPath2 = require('./expandPath2')
|
|
|
24
24
|
* @example
|
|
25
25
|
* let newarc = expand({delta: 5, corners: 'edge'}, arc({}))
|
|
26
26
|
* let newsquare = expand({delta: 5, corners: 'chamfer'}, square({size: 30}))
|
|
27
|
-
* let
|
|
27
|
+
* let newcuboid = expand({delta: 2, corners: 'round'}, cuboid({size: [20, 25, 5]}))
|
|
28
28
|
*/
|
|
29
29
|
const expand = (options, ...objects) => {
|
|
30
30
|
objects = flatten(objects)
|
|
@@ -19,14 +19,8 @@ const geom2 = require('../../geometries/geom2')
|
|
|
19
19
|
* @alias module:modeling/extrusions.extrudeHelical
|
|
20
20
|
*
|
|
21
21
|
* @example
|
|
22
|
-
* const myshape =
|
|
23
|
-
*
|
|
24
|
-
* angle: Math.PI * 4,
|
|
25
|
-
* pitch: 10,
|
|
26
|
-
* segmentsPerRotation: 64
|
|
27
|
-
* },
|
|
28
|
-
* circle({size: 3, center: [10, 0]})
|
|
29
|
-
* )
|
|
22
|
+
* const myshape = circle({size: 3, center: [10, 0]}) // position for extrusion about Z
|
|
23
|
+
* const mycoil = extrudeHelical({angle: TAU*2, pitch: 10, segmentsPerRotation: 64}, myshape))
|
|
30
24
|
*/
|
|
31
25
|
const extrudeHelical = (options, geometry) => {
|
|
32
26
|
const defaults = {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* In all cases, the function returns the results, and never changes the original shapes.
|
|
4
4
|
* @module modeling/extrusions
|
|
5
5
|
* @example
|
|
6
|
-
* const { extrudeLinear, extrudeRectangular, extrudeRotate } = require('@jscad/modeling').extrusions
|
|
6
|
+
* const { extrudeHelical, extrudeLinear, extrudeRectangular, extrudeRotate, project, slice } = require('@jscad/modeling').extrusions
|
|
7
7
|
*/
|
|
8
8
|
module.exports = {
|
|
9
9
|
extrudeFromSlices: require('./extrudeFromSlices'),
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* In all cases, the function returns the results, and never changes the original shapes.
|
|
5
5
|
* @module modeling/hulls
|
|
6
6
|
* @example
|
|
7
|
-
* const { hull, hullChain } = require('@jscad/modeling').hulls
|
|
7
|
+
* const { hull, hullChain, hullPoints2, hullPoints3 } = require('@jscad/modeling').hulls
|
|
8
8
|
*/
|
|
9
9
|
module.exports = {
|
|
10
10
|
hull: require('./hull'),
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* In all cases, these functions returns the results, and never changes the original geometry.
|
|
4
4
|
* @module modeling/modifiers
|
|
5
5
|
* @example
|
|
6
|
-
* const { snap } = require('@jscad/modeling').modifiers
|
|
6
|
+
* const { generalize, snap, retessellate } = require('@jscad/modeling').modifiers
|
|
7
7
|
*/
|
|
8
8
|
module.exports = {
|
|
9
9
|
generalize: require('./generalize'),
|
|
@@ -35,7 +35,7 @@ const snapGeom3 = (geometry) => {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* Snap the given geometries to the
|
|
38
|
+
* Snap the given geometries to the precision (calculated epsilon) of the geometry.
|
|
39
39
|
* @see measurements.measureEpsilon()
|
|
40
40
|
* @param {...Object} geometries - the geometries to snap
|
|
41
41
|
* @return {Object|Array} the snapped geometry, or a list of snapped geometries
|
package/src/primitives/arc.js
CHANGED
|
@@ -17,6 +17,8 @@ const { isGT, isGTE, isNumberArray } = require('./commonChecks')
|
|
|
17
17
|
* @param {Boolean} [options.makeTangent=false] - adds line segments at both ends of the arc to ensure that the gradients at the edges are tangent
|
|
18
18
|
* @returns {path2} new 2D path
|
|
19
19
|
* @alias module:modeling/primitives.arc
|
|
20
|
+
* @example
|
|
21
|
+
* let myshape = arc({ center: [-1, -1], radius: 2, endAngle: (TAU / 4)})
|
|
20
22
|
*/
|
|
21
23
|
const arc = (options) => {
|
|
22
24
|
const defaults = {
|
|
@@ -71,8 +71,8 @@ const polygon = (options) => {
|
|
|
71
71
|
})
|
|
72
72
|
|
|
73
73
|
// convert the list of sides into a geometry
|
|
74
|
-
let geometry =
|
|
75
|
-
if (orientation
|
|
74
|
+
let geometry = geom2.create(sides)
|
|
75
|
+
if (orientation === 'clockwise') {
|
|
76
76
|
geometry = geom2.reverse(geometry)
|
|
77
77
|
}
|
|
78
78
|
return geometry
|
|
@@ -56,7 +56,7 @@ test('polygon: providing object.points (array) and object.path (array) creates e
|
|
|
56
56
|
test('polygon: clockwise points', (t) => {
|
|
57
57
|
const poly = polygon({
|
|
58
58
|
points: [[-10, -0], [-10, -10], [-15, -5]],
|
|
59
|
-
orientation:
|
|
59
|
+
orientation: 'clockwise'
|
|
60
60
|
})
|
|
61
61
|
t.is(poly.sides.length, 3)
|
|
62
62
|
t.is(measureArea(poly), 25)
|
|
@@ -5,6 +5,7 @@ const { isNumberArray } = require('./commonChecks')
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Construct a polyhedron in three dimensional space from the given set of 3D points and faces.
|
|
8
|
+
*
|
|
8
9
|
* The faces can define outward or inward facing polygons (orientation).
|
|
9
10
|
* However, each face must define a counter clockwise rotation of points which follows the right hand rule.
|
|
10
11
|
* @param {Object} options - options for construction
|
|
@@ -18,7 +19,7 @@ const { isNumberArray } = require('./commonChecks')
|
|
|
18
19
|
* @example
|
|
19
20
|
* let mypoints = [ [10, 10, 0], [10, -10, 0], [-10, -10, 0], [-10, 10, 0], [0, 0, 10] ]
|
|
20
21
|
* let myfaces = [ [0, 1, 4], [1, 2, 4], [2, 3, 4], [3, 0, 4], [1, 0, 3], [2, 1, 3] ]
|
|
21
|
-
* let myshape = polyhedron({points:
|
|
22
|
+
* let myshape = polyhedron({points: mypoints, faces: myfaces, orientation: 'inward'})
|
|
22
23
|
*/
|
|
23
24
|
const polyhedron = (options) => {
|
|
24
25
|
const defaults = {
|
package/src/primitives/torus.js
CHANGED
|
@@ -43,7 +43,7 @@ const torus = (options) => {
|
|
|
43
43
|
if (!isGTE(startAngle, 0)) throw new Error('startAngle must be positive')
|
|
44
44
|
if (!isGT(outerRotation, 0)) throw new Error('outerRotation must be greater than zero')
|
|
45
45
|
|
|
46
|
-
if (innerRadius >= outerRadius) throw new Error('inner circle is
|
|
46
|
+
if (innerRadius >= outerRadius) throw new Error('inner circle is too large to rotate about the outer circle')
|
|
47
47
|
|
|
48
48
|
let innerCircle = circle({ radius: innerRadius, segments: innerSegments })
|
|
49
49
|
|
package/src/text/vectorChar.js
CHANGED
|
@@ -22,11 +22,8 @@ const vectorParams = require('./vectorParams')
|
|
|
22
22
|
*
|
|
23
23
|
* @example
|
|
24
24
|
* let vectorCharObject = vectorChar()
|
|
25
|
-
* or
|
|
26
25
|
* let vectorCharObject = vectorChar('A')
|
|
27
|
-
* or
|
|
28
26
|
* let vectorCharObject = vectorChar({ xOffset: 57 }, 'C')
|
|
29
|
-
* or
|
|
30
27
|
* let vectorCharObject = vectorChar({ xOffset: 78, input: '!' })
|
|
31
28
|
*/
|
|
32
29
|
const vectorChar = (options, char) => {
|
package/src/text/vectorText.js
CHANGED
|
@@ -35,11 +35,8 @@ const translateLine = (options, line) => {
|
|
|
35
35
|
*
|
|
36
36
|
* @example
|
|
37
37
|
* let textSegments = vectorText()
|
|
38
|
-
* or
|
|
39
38
|
* let textSegments = vectorText('OpenJSCAD')
|
|
40
|
-
* or
|
|
41
39
|
* let textSegments = vectorText({ yOffset: -50 }, 'OpenJSCAD')
|
|
42
|
-
* or
|
|
43
40
|
* let textSegments = vectorText({ yOffset: -80, input: 'OpenJSCAD' })
|
|
44
41
|
*/
|
|
45
42
|
const vectorText = (options, text) => {
|
package/src/utils/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Utility functions of various sorts.
|
|
2
|
+
* Utility functions of various sorts, including conversions from different angular measures.
|
|
3
3
|
* @module modeling/utils
|
|
4
4
|
* @example
|
|
5
|
-
* const {
|
|
5
|
+
* const { areAllShapesTheSameType, degToRad, radiusToSegments, radToDeg } = require('@jscad/modeling').utils
|
|
6
6
|
*/
|
|
7
7
|
module.exports = {
|
|
8
8
|
areAllShapesTheSameType: require('./areAllShapesTheSameType'),
|