three-cad-viewer 2.1.2 → 2.2.0

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.
@@ -1,183 +1,150 @@
1
- import {
2
- FileLoader,
3
- Loader,
4
- ShapePath
5
- } from 'three';
1
+ import { FileLoader, Loader, ShapePath } from "three";
6
2
 
7
3
  class FontLoader extends Loader {
8
-
9
- constructor( manager ) {
10
-
11
- super( manager );
12
-
13
- }
14
-
15
- load( url, onLoad, onProgress, onError ) {
16
-
17
- const scope = this;
18
-
19
- const loader = new FileLoader( this.manager );
20
- loader.setPath( this.path );
21
- loader.setRequestHeader( this.requestHeader );
22
- loader.setWithCredentials( this.withCredentials );
23
- loader.load( url, function ( text ) {
24
-
25
- const font = scope.parse( JSON.parse( text ) );
26
-
27
- if ( onLoad ) onLoad( font );
28
-
29
- }, onProgress, onError );
30
-
31
- }
32
-
33
- parse( json ) {
34
-
35
- return new Font( json );
36
-
37
- }
38
-
4
+ constructor(manager) {
5
+ super(manager);
6
+ }
7
+
8
+ load(url, onLoad, onProgress, onError) {
9
+ const scope = this;
10
+
11
+ const loader = new FileLoader(this.manager);
12
+ loader.setPath(this.path);
13
+ loader.setRequestHeader(this.requestHeader);
14
+ loader.setWithCredentials(this.withCredentials);
15
+ loader.load(
16
+ url,
17
+ function (text) {
18
+ const font = scope.parse(JSON.parse(text));
19
+
20
+ if (onLoad) onLoad(font);
21
+ },
22
+ onProgress,
23
+ onError,
24
+ );
25
+ }
26
+
27
+ parse(json) {
28
+ return new Font(json);
29
+ }
39
30
  }
40
31
 
41
32
  //
42
33
 
43
34
  class Font {
35
+ constructor(data) {
36
+ this.isFont = true;
44
37
 
45
- constructor( data ) {
46
-
47
- this.isFont = true;
48
-
49
- this.type = 'Font';
50
-
51
- this.data = data;
52
-
53
- }
54
-
55
- generateShapes( text, size = 100 ) {
56
-
57
- const shapes = [];
58
- const paths = createPaths( text, size, this.data );
59
-
60
- for ( let p = 0, pl = paths.length; p < pl; p ++ ) {
61
-
62
- shapes.push( ...paths[ p ].toShapes() );
38
+ this.type = "Font";
63
39
 
64
- }
40
+ this.data = data;
41
+ }
65
42
 
66
- return shapes;
43
+ generateShapes(text, size = 100) {
44
+ const shapes = [];
45
+ const paths = createPaths(text, size, this.data);
67
46
 
68
- }
47
+ for (let p = 0, pl = paths.length; p < pl; p++) {
48
+ shapes.push(...paths[p].toShapes());
49
+ }
69
50
 
51
+ return shapes;
52
+ }
70
53
  }
71
54
 
72
- function createPaths( text, size, data ) {
55
+ function createPaths(text, size, data) {
56
+ const chars = Array.from(text);
57
+ const scale = size / data.resolution;
58
+ const line_height =
59
+ (data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness) *
60
+ scale;
73
61
 
74
- const chars = Array.from( text );
75
- const scale = size / data.resolution;
76
- const line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
62
+ const paths = [];
77
63
 
78
- const paths = [];
64
+ let offsetX = 0,
65
+ offsetY = 0;
79
66
 
80
- let offsetX = 0, offsetY = 0;
67
+ for (let i = 0; i < chars.length; i++) {
68
+ const char = chars[i];
81
69
 
82
- for ( let i = 0; i < chars.length; i ++ ) {
83
-
84
- const char = chars[ i ];
85
-
86
- if ( char === '\n' ) {
87
-
88
- offsetX = 0;
89
- offsetY -= line_height;
90
-
91
- } else {
92
-
93
- const ret = createPath( char, scale, offsetX, offsetY, data );
94
- offsetX += ret.offsetX;
95
- paths.push( ret.path );
96
-
97
- }
98
-
99
- }
100
-
101
- return paths;
70
+ if (char === "\n") {
71
+ offsetX = 0;
72
+ offsetY -= line_height;
73
+ } else {
74
+ const ret = createPath(char, scale, offsetX, offsetY, data);
75
+ offsetX += ret.offsetX;
76
+ paths.push(ret.path);
77
+ }
78
+ }
102
79
 
80
+ return paths;
103
81
  }
104
82
 
105
- function createPath( char, scale, offsetX, offsetY, data ) {
106
-
107
- const glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
108
-
109
- if ( ! glyph ) {
110
-
111
- console.error( 'THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + '.' );
112
-
113
- return;
114
-
115
- }
116
-
117
- const path = new ShapePath();
118
-
119
- let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
120
-
121
- if ( glyph.o ) {
122
-
123
- const outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
124
-
125
- for ( let i = 0, l = outline.length; i < l; ) {
126
-
127
- const action = outline[ i ++ ];
128
-
129
- switch ( action ) {
130
-
131
- case 'm': // moveTo
132
-
133
- x = outline[ i ++ ] * scale + offsetX;
134
- y = outline[ i ++ ] * scale + offsetY;
83
+ function createPath(char, scale, offsetX, offsetY, data) {
84
+ const glyph = data.glyphs[char] || data.glyphs["?"];
135
85
 
136
- path.moveTo( x, y );
86
+ if (!glyph) {
87
+ console.error(
88
+ `THREE.Font: character "${char}" does not exists in font family ${data.familyName}`,
89
+ );
137
90
 
138
- break;
91
+ return;
92
+ }
139
93
 
140
- case 'l': // lineTo
94
+ const path = new ShapePath();
141
95
 
142
- x = outline[ i ++ ] * scale + offsetX;
143
- y = outline[ i ++ ] * scale + offsetY;
96
+ let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
144
97
 
145
- path.lineTo( x, y );
98
+ if (glyph.o) {
99
+ const outline =
100
+ glyph._cachedOutline || (glyph._cachedOutline = glyph.o.split(" "));
146
101
 
147
- break;
102
+ for (let i = 0, l = outline.length; i < l; ) {
103
+ const action = outline[i++];
148
104
 
149
- case 'q': // quadraticCurveTo
105
+ switch (action) {
106
+ case "m": // moveTo
107
+ x = outline[i++] * scale + offsetX;
108
+ y = outline[i++] * scale + offsetY;
150
109
 
151
- cpx = outline[ i ++ ] * scale + offsetX;
152
- cpy = outline[ i ++ ] * scale + offsetY;
153
- cpx1 = outline[ i ++ ] * scale + offsetX;
154
- cpy1 = outline[ i ++ ] * scale + offsetY;
110
+ path.moveTo(x, y);
155
111
 
156
- path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
112
+ break;
157
113
 
158
- break;
114
+ case "l": // lineTo
115
+ x = outline[i++] * scale + offsetX;
116
+ y = outline[i++] * scale + offsetY;
159
117
 
160
- case 'b': // bezierCurveTo
118
+ path.lineTo(x, y);
161
119
 
162
- cpx = outline[ i ++ ] * scale + offsetX;
163
- cpy = outline[ i ++ ] * scale + offsetY;
164
- cpx1 = outline[ i ++ ] * scale + offsetX;
165
- cpy1 = outline[ i ++ ] * scale + offsetY;
166
- cpx2 = outline[ i ++ ] * scale + offsetX;
167
- cpy2 = outline[ i ++ ] * scale + offsetY;
120
+ break;
168
121
 
169
- path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
122
+ case "q": // quadraticCurveTo
123
+ cpx = outline[i++] * scale + offsetX;
124
+ cpy = outline[i++] * scale + offsetY;
125
+ cpx1 = outline[i++] * scale + offsetX;
126
+ cpy1 = outline[i++] * scale + offsetY;
170
127
 
171
- break;
128
+ path.quadraticCurveTo(cpx1, cpy1, cpx, cpy);
172
129
 
173
- }
130
+ break;
174
131
 
175
- }
132
+ case "b": // bezierCurveTo
133
+ cpx = outline[i++] * scale + offsetX;
134
+ cpy = outline[i++] * scale + offsetY;
135
+ cpx1 = outline[i++] * scale + offsetX;
136
+ cpy1 = outline[i++] * scale + offsetY;
137
+ cpx2 = outline[i++] * scale + offsetX;
138
+ cpy2 = outline[i++] * scale + offsetY;
176
139
 
177
- }
140
+ path.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, cpx, cpy);
178
141
 
179
- return { offsetX: glyph.ha * scale, path: path };
142
+ break;
143
+ }
144
+ }
145
+ }
180
146
 
147
+ return { offsetX: glyph.ha * scale, path: path };
181
148
  }
182
149
 
183
150
  export { FontLoader, Font };
package/src/grid.js CHANGED
@@ -1,37 +1,90 @@
1
1
  import * as THREE from "three";
2
+ import { Font } from "./fontloader/FontLoader.js";
3
+ import { helvetiker } from "./font.js";
2
4
 
3
5
  class Grid {
4
- constructor(display, bbox, ticks, axes0, grid, flipY) {
6
+ constructor(display, bbox, ticks, centerGrid, axes0, grid, flipY, theme) {
5
7
  if (ticks === undefined) {
6
8
  ticks = 10;
7
9
  }
8
10
  this.display = display;
9
11
  this.bbox = bbox;
10
-
12
+ this.centerGrid = centerGrid;
11
13
  this.grid = grid;
12
14
  this.allGrid = grid[0] | grid[1] | grid[2];
15
+ const s = new THREE.Vector3();
16
+ bbox.getSize(s);
17
+ const s2 = Math.max(s.x, s.y, s.z);
18
+ // const s2 = bbox.boundingSphere().radius;
13
19
 
14
20
  this.gridHelper = [];
15
21
  // in case the bbox has the same siez as the nice grid there should be
16
22
  // a margin bewteen grid and object. Hence factor 1.1
17
23
  var [axisStart, axisEnd, niceTick] = this.niceBounds(
18
- -bbox.max_dist_from_center() * 1.1,
19
- bbox.max_dist_from_center() * 1.1,
24
+ -s2 * 1.05,
25
+ s2 * 1.05,
20
26
  2 * ticks,
21
27
  );
22
28
  this.size = axisEnd - axisStart;
23
29
 
30
+ const font = new Font(helvetiker);
31
+
24
32
  this.ticks = niceTick;
25
33
 
26
34
  for (var i = 0; i < 3; i++) {
27
- this.gridHelper.push(
35
+ var group = new THREE.Group();
36
+ group.name = `GridHelper-${i}`;
37
+ group.add(
28
38
  new THREE.GridHelper(
29
39
  this.size,
30
40
  this.size / this.ticks,
31
- 0x888888,
32
- 0xcccccc,
41
+ theme === "dark" ? 0xcccccc : 0x777777,
42
+ theme == "dark" ? 0x999999 : 0xbbbbbb,
33
43
  ),
34
44
  );
45
+ const mat = new THREE.LineBasicMaterial({
46
+ color:
47
+ theme === "dark"
48
+ ? new THREE.Color(0.5, 0.5, 0.5)
49
+ : new THREE.Color(0.4, 0.4, 0.4),
50
+ side: THREE.DoubleSide,
51
+ });
52
+ var dir;
53
+ var geom;
54
+ for (var x = -this.size / 2; x <= this.size / 2; x += this.ticks) {
55
+ geom = this.createNumber(x, font);
56
+ if (i == 0) {
57
+ geom.rotateX(-Math.PI / 2);
58
+ geom.rotateY(Math.PI / 2);
59
+ } else if (i == 1) {
60
+ geom.rotateX(Math.PI / 2);
61
+ geom.rotateY(-Math.PI / 2);
62
+ } else {
63
+ geom.rotateX(Math.PI / 2);
64
+ geom.rotateY(-Math.PI / 2);
65
+ }
66
+ const label = new THREE.Mesh(geom, mat);
67
+ dir = i == 1 ? -1 : 1;
68
+ label.position.set(dir * x, 0, 0);
69
+ group.add(label);
70
+
71
+ if (Math.abs(x) < 1e-6) continue;
72
+
73
+ geom = this.createNumber(x, font);
74
+ if (i == 0) {
75
+ geom.rotateX(-Math.PI / 2);
76
+ } else if (i == 1) {
77
+ geom.rotateX(-Math.PI / 2);
78
+ geom.rotateZ(Math.PI);
79
+ } else {
80
+ geom.rotateX(Math.PI / 2);
81
+ }
82
+ const label2 = new THREE.Mesh(geom, mat);
83
+ dir = i == 0 ? -1 : 1;
84
+ label2.position.set(0, 0, dir * x);
85
+ group.add(label2);
86
+ }
87
+ this.gridHelper.push(group);
35
88
  }
36
89
 
37
90
  this.gridHelper[0].rotateX(Math.PI / 2);
@@ -43,6 +96,21 @@ class Grid {
43
96
  this.setVisible();
44
97
  }
45
98
 
99
+ createNumber(x, font) {
100
+ // experimentally detected: p1=(size=640, font_size=7.1) p2=(size=2.2, font_size=0.035)
101
+ const m = (0.035 - 7.1) / (2.2 - 640);
102
+ const fontSize = m * (this.size - 640) + 7.1;
103
+
104
+ const shape = font.generateShapes(x.toFixed(1), fontSize);
105
+ var geom = new THREE.ShapeGeometry(shape);
106
+
107
+ geom.computeBoundingBox();
108
+ var xMid = -0.5 * (geom.boundingBox.max.x - geom.boundingBox.min.x);
109
+ var yMid = -0.5 * (geom.boundingBox.max.y - geom.boundingBox.min.y);
110
+ geom.translate(xMid, yMid, 0);
111
+ return geom;
112
+ }
113
+
46
114
  // https://stackoverflow.com/questions/4947682/intelligently-calculating-chart-tick-positions
47
115
  niceNumber(value, round) {
48
116
  var exponent = Math.floor(Math.log10(value));
@@ -109,7 +177,7 @@ class Grid {
109
177
  setGrid(action, flag = null) {
110
178
  switch (action) {
111
179
  case "grid":
112
- this.allGrid = (flag == null) ? !this.allGrid : flag;
180
+ this.allGrid = flag == null ? !this.allGrid : flag;
113
181
  this.grid[0] = this.allGrid;
114
182
  this.grid[1] = this.allGrid;
115
183
  this.grid[2] = this.allGrid;
@@ -139,17 +207,25 @@ class Grid {
139
207
  for (var i = 0; i < 3; i++) {
140
208
  this.gridHelper[i].position.set(0, 0, 0);
141
209
  }
142
- this.gridHelper[0].position.z = -this.size / 2;
143
- this.gridHelper[1].position.y = ((flipY ? 1 : -1) * this.size) / 2;
144
- this.gridHelper[2].position.x = -this.size / 2;
210
+ this.gridHelper[0].position.z = this.centerGrid ? 0 : -this.size / 2;
211
+ this.gridHelper[1].position.y = this.centerGrid
212
+ ? 0
213
+ : ((flipY ? 1 : -1) * this.size) / 2;
214
+ this.gridHelper[2].position.x = this.centerGrid ? 0 : -this.size / 2;
145
215
  } else {
146
216
  const c = this.bbox.center();
147
217
  for (i = 0; i < 3; i++) {
148
218
  this.gridHelper[i].position.set(...c);
149
219
  }
150
- this.gridHelper[0].position.z = -this.size / 2 + c[2];
151
- this.gridHelper[1].position.y = ((flipY ? 1 : -1) * this.size) / 2 + c[1];
152
- this.gridHelper[2].position.x = -this.size / 2 + c[0];
220
+ this.gridHelper[0].position.z = this.centerGrid
221
+ ? c[2]
222
+ : -this.size / 2 + c[2];
223
+ this.gridHelper[1].position.y = this.centerGrid
224
+ ? c[1]
225
+ : ((flipY ? 1 : -1) * this.size) / 2 + c[1];
226
+ this.gridHelper[2].position.x = this.centerGrid
227
+ ? c[0]
228
+ : -this.size / 2 + c[0];
153
229
  }
154
230
  }
155
231
 
package/src/icons.js CHANGED
@@ -45,7 +45,6 @@ import dark_shape_no from "../icons/dark/shape_no.svg";
45
45
  import dark_stop from "../icons/dark/stop.svg";
46
46
  import dark_top from "../icons/dark/top.svg";
47
47
 
48
-
49
48
  import dark_axes from "../icons/dark/axes.svg";
50
49
  import dark_axes0 from "../icons/dark/axes0.svg";
51
50
  import dark_grid from "../icons/dark/grid.svg";
@@ -68,7 +67,6 @@ import light_angle from "../icons/light/angle.svg";
68
67
  import light_transparent from "../icons/light/transparent.svg";
69
68
  import light_blackedges from "../icons/light/black_edges.svg";
70
69
 
71
-
72
70
  const icons = {
73
71
  bottom: { light: light_bottom, dark: dark_bottom },
74
72
  front: { light: light_front, dark: dark_front },
package/src/index.html CHANGED
@@ -122,18 +122,29 @@
122
122
  </div>
123
123
  </div>
124
124
  <div class="tcv_clip_checks">
125
- <span class="tcv_tooltip" data-tooltip="Use intersection clipping">
126
- <span class="tcv_label">Intersection</span><input
127
- class='tcv_clip_intersection tcv_check' type="checkbox" />
128
- </span>
129
- <span class="tcv_tooltip" data-tooltip="Show clipping planes">
130
- <span class="tcv_label">Planes</span><input
131
- class='tcv_clip_plane_helpers tcv_axes0 tcv_check' type="checkbox" />
125
+ <div>
126
+ <span class="tcv_tooltip" data-tooltip="Use intersection clipping">
127
+ <input class='tcv_clip_intersection tcv_check' type="checkbox" />
128
+ <span class="tcv_label">Intersection</span>
129
+ </span>
130
+ <span class="tcv_tooltip" data-tooltip="Show clipping planes">
131
+ <input class='tcv_clip_plane_helpers tcv_axes0 tcv_check' type="checkbox" />
132
+ <span class="tcv_label">Planes</span>
133
+ </span>
134
+ </div>
135
+ <span class="tcv_tooltip" data-tooltip="Use object color caps instead of RGB">
136
+ <input class='tcv_clip_caps tcv_axes0 tcv_check' type="checkbox" />
137
+ <span class="tcv_label">Use object color caps</span>
132
138
  </span>
133
139
  </div>
134
140
  </div>
135
141
  <div class="tcv_cad_material_container">
136
- <div class="tcv_material_ambientlight tcv_label tcv_clip_checks">
142
+ <div class="tcv_cad_tree_toggles">
143
+ <span class="tcv_tooltip" data-tooltip="Reset to original values">
144
+ <input class='tcv_material_reset tcv_btn tcv_small_btn' value="R" type="button" />
145
+ </span>
146
+ </div>
147
+ <div class="tcv_material_ambientlight tcv_label">
137
148
  Ambient light intensity (%)
138
149
  </div>
139
150
  <div class="tcv_slider_group">