@toolpath/viewer 0.3.1 → 0.4.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.
package/dist/engine/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PartModel, a as PartMeshRefs } from '../normalize-
|
|
2
|
-
export { E as EnginePart, b as EnginePartProps, M as MIN_KERNEL_VERSION, c as assertSupportedKernelVersion, n as normalizePartReport, s as smoothRegionNormals } from '../normalize-
|
|
1
|
+
import { P as PartModel, a as PartMeshRefs } from '../normalize-BXIGoZmc.js';
|
|
2
|
+
export { E as EnginePart, b as EnginePartProps, M as MIN_KERNEL_VERSION, c as assertSupportedKernelVersion, n as normalizePartReport, s as smoothRegionNormals } from '../normalize-BXIGoZmc.js';
|
|
3
3
|
import { BufferGeometry } from 'three';
|
|
4
4
|
import 'react';
|
|
5
5
|
|
package/dist/engine/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { B as BuildPickInput, C as CAD_CAMERA_UP, k as CANDIDATE_WEIGHT, D as DEFAULT_FIT_MARGIN, l as DEFAULT_THEME, m as DIRECTION_COLORS, o as EXCLUDE_FROM_FRAME, E as EnginePart, p as FeatureHighlight, H as HANDLE_PIXELS, q as HIGHLIGHT_COLORS, r as HIGHLIGHT_WEIGHT, t as HOVER_WEIGHT, u as HighlightLayers, K as KnownFeatureType, N as NO_MODIFIERS, v as PERSPECTIVE_FOV, w as PICKED_SURFACE_LABEL, x as PartMesh, y as PartMeshProps, a as PartMeshRefs, z as PartObject, A as PartPick, G as PickModifiers, I as REGION_ATTRIBUTE, J as RegionHighlight, L as RegionPaint, S as SECTION_RENDER_ORDER, O as SceneBounds, Q as SectionAnchor, U as SectionBounds, W as SectionOptions, X as SectionPlacement, Y as SectionState, Z as SectionView, _ as ViewportSize, $ as applyHighlightLayers, a0 as applyProjection, a1 as aspectRatio, a2 as boundsFromBox, a3 as buildPick, a4 as buildRegionAttribute, a5 as buildRegionTexels, a6 as cadViewDirections, a7 as contentBounds, a8 as createPart, a9 as currentViewDirection, aa as defaultBounds, ab as directionColor, ac as dragPlane, ad as fitDistance, ae as focusForPick, n as normalizePartReport, af as orthographicHalfHeight, ag as perspectiveFitDistance, ah as pickedStartDepth, ai as resolveSectionPlane, aj as resolveTheme, ak as screenLength, al as sectionBounds, am as sectionConstant, an as sectionDepth, ao as sectionDepthConstant, ap as sectionDepthRange, aq as sectionFromPick, ar as sectionOffset, as as sectionPlane, s as smoothRegionNormals, at as startPosition, au as themesEqual, av as viewDirection } from './normalize-
|
|
1
|
+
import { P as PartModel, V as Vec3, d as ViewerTheme, e as PartModelRegion, f as ViewerCamera, g as ViewerView, h as Projection, T as TriangleRange, F as FeatureTag, R as RegionIndex, i as PartModelFeature, j as FeatureType } from './normalize-BXIGoZmc.js';
|
|
2
|
+
export { B as BuildPickInput, C as CAD_CAMERA_UP, k as CANDIDATE_WEIGHT, D as DEFAULT_FIT_MARGIN, l as DEFAULT_THEME, m as DIRECTION_COLORS, o as EXCLUDE_FROM_FRAME, E as EnginePart, p as FeatureHighlight, H as HANDLE_PIXELS, q as HIGHLIGHT_COLORS, r as HIGHLIGHT_WEIGHT, t as HOVER_WEIGHT, u as HighlightLayers, K as KnownFeatureType, N as NO_MODIFIERS, v as PERSPECTIVE_FOV, w as PICKED_SURFACE_LABEL, x as PartMesh, y as PartMeshProps, a as PartMeshRefs, z as PartObject, A as PartPick, G as PickModifiers, I as REGION_ATTRIBUTE, J as RegionHighlight, L as RegionPaint, S as SECTION_RENDER_ORDER, O as SceneBounds, Q as SectionAnchor, U as SectionBounds, W as SectionOptions, X as SectionPlacement, Y as SectionState, Z as SectionView, _ as ViewportSize, $ as applyHighlightLayers, a0 as applyProjection, a1 as aspectRatio, a2 as boundsFromBox, a3 as buildPick, a4 as buildRegionAttribute, a5 as buildRegionTexels, a6 as cadViewDirections, a7 as contentBounds, a8 as createPart, a9 as currentViewDirection, aa as defaultBounds, ab as directionColor, ac as dragPlane, ad as fitDistance, ae as focusForPick, n as normalizePartReport, af as orthographicHalfHeight, ag as perspectiveFitDistance, ah as pickedStartDepth, ai as resolveSectionPlane, aj as resolveTheme, ak as screenLength, al as sectionBounds, am as sectionConstant, an as sectionDepth, ao as sectionDepthConstant, ap as sectionDepthRange, aq as sectionFromPick, ar as sectionOffset, as as sectionPlane, s as smoothRegionNormals, at as startPosition, au as themesEqual, av as viewDirection } from './normalize-BXIGoZmc.js';
|
|
3
|
+
import { BufferGeometry, CanvasTexture, Vector3, Box3 } from 'three';
|
|
3
4
|
import * as react from 'react';
|
|
4
5
|
import { RefObject, ReactNode, CSSProperties } from 'react';
|
|
5
|
-
import { BufferGeometry, CanvasTexture, Vector3, Box3 } from 'three';
|
|
6
6
|
import CameraControls from 'camera-controls';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Every face's neighbours, keyed by region index.
|
|
10
|
+
*
|
|
11
|
+
* One pass over the triangles: each contributes three edges, each edge names
|
|
12
|
+
* the region that owns it, and any edge named by two regions joins them.
|
|
13
|
+
*/
|
|
14
|
+
declare function regionAdjacency(model: PartModel, geometry: BufferGeometry): Map<number, Set<number>>;
|
|
15
|
+
|
|
8
16
|
/**
|
|
9
17
|
* The 26 standard views: the six faces of the cube, the twelve edges between
|
|
10
18
|
* them, and its eight corners.
|
|
@@ -39,6 +47,21 @@ declare function viewVector(name: ViewName): Vec3;
|
|
|
39
47
|
* come from here.
|
|
40
48
|
*/
|
|
41
49
|
declare function viewUp(direction: Vec3): Vec3;
|
|
50
|
+
/**
|
|
51
|
+
* The squared up vector nearest to the one the camera already has.
|
|
52
|
+
*
|
|
53
|
+
* A view has four square orientations, not one: {@link viewUp} rolled by 0°,
|
|
54
|
+
* 90°, 180° and 270° about the view direction. Snapping to the canonical one
|
|
55
|
+
* would spin the part on the way to a view somebody asked for because it was
|
|
56
|
+
* already nearly in front of them — arrive at the bottom view from the right
|
|
57
|
+
* and the part turns a quarter of a turn for no reason they can see.
|
|
58
|
+
*
|
|
59
|
+
* So the roll is chosen, not imposed: of the four, the one closest to where the
|
|
60
|
+
* camera is looking from now. The view still lands square — Bottom simply lands
|
|
61
|
+
* square in whichever of its four ways was already nearest, which is how the
|
|
62
|
+
* Fusion cube behaves and what somebody arriving from it will expect.
|
|
63
|
+
*/
|
|
64
|
+
declare function squaredUp(direction: Vec3, currentUp: Vec3): Vec3;
|
|
42
65
|
/**
|
|
43
66
|
* Half-width of a face panel, where the cube's half-extent is 1 — so the
|
|
44
67
|
* chamfer taken off each edge is the remaining `1 - CHAMFER`.
|
|
@@ -134,10 +157,15 @@ interface DirectionArrowsProps {
|
|
|
134
157
|
*/
|
|
135
158
|
activeDirection?: number | null;
|
|
136
159
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
160
|
+
* Which arrows are drawn, without scoping anything: `null` for all of them,
|
|
161
|
+
* an index for one, `-1` for none — and **a list of indices for a set**, which
|
|
162
|
+
* is how a plan draws only the ways up it has confirmed.
|
|
163
|
+
*
|
|
164
|
+
* One prop rather than a singular and a plural, because two would need a rule
|
|
165
|
+
* about which wins, and a caller with an answer to give should not also have
|
|
166
|
+
* to say where to put it. Falls back to `activeDirection`.
|
|
139
167
|
*/
|
|
140
|
-
shownDirection?: number | null;
|
|
168
|
+
shownDirection?: number | readonly number[] | null;
|
|
141
169
|
/**
|
|
142
170
|
* A direction being named, drawn while it is aimed. Not a candidate and not a
|
|
143
171
|
* selection: a way up that does not exist yet, so it is drawn over the part —
|
|
@@ -227,6 +255,37 @@ interface TapTracker {
|
|
|
227
255
|
* and a listener that runs after `stopPropagation` runs never.
|
|
228
256
|
*/
|
|
229
257
|
declare function trackTaps(element: HTMLElement): TapTracker;
|
|
258
|
+
/**
|
|
259
|
+
* How long between two presses still reads as one gesture, in milliseconds.
|
|
260
|
+
*
|
|
261
|
+
* The browser's own `dblclick` threshold is a platform setting and is not
|
|
262
|
+
* readable from script, so a hand-paired gesture has to pick a number. 400ms is
|
|
263
|
+
* inside every default and outside a deliberate pair of separate clicks.
|
|
264
|
+
*/
|
|
265
|
+
declare const DOUBLE_TAP_MS = 400;
|
|
266
|
+
interface DoubleTapPoint extends TapPoint {
|
|
267
|
+
readonly timeStamp: number;
|
|
268
|
+
}
|
|
269
|
+
interface DoubleTapTracker {
|
|
270
|
+
/** Whether this press completes a double tap begun by the last one. */
|
|
271
|
+
isDouble(event: DoubleTapPoint): boolean;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Pairing presses into a double tap by hand.
|
|
275
|
+
*
|
|
276
|
+
* Needed because `dblclick` fires for the **primary button only** — there is no
|
|
277
|
+
* such event for the middle button, however many times it is pressed. So a
|
|
278
|
+
* middle-button gesture has to be assembled from single presses.
|
|
279
|
+
*
|
|
280
|
+
* Position matters as well as time: two presses at opposite corners inside the
|
|
281
|
+
* window are two clicks that happened to be quick, not one gesture, and
|
|
282
|
+
* treating them as a double would re-frame the view out from under somebody
|
|
283
|
+
* who was doing something else. The same {@link TAP_SLOP} the click guard uses.
|
|
284
|
+
*
|
|
285
|
+
* A completed double clears the state rather than leaving it, so three presses
|
|
286
|
+
* are one double and one single rather than two overlapping doubles.
|
|
287
|
+
*/
|
|
288
|
+
declare function trackDoubleTaps(within?: number, slop?: number): DoubleTapTracker;
|
|
230
289
|
|
|
231
290
|
/**
|
|
232
291
|
* A click that is a click, for anything inside the canvas.
|
|
@@ -368,6 +427,15 @@ interface CadCameraControlsProps {
|
|
|
368
427
|
* about an orbit control.
|
|
369
428
|
*/
|
|
370
429
|
freeOrbit?: boolean;
|
|
430
|
+
/**
|
|
431
|
+
* What the wheel zooms toward: the pointer, or the middle of the view.
|
|
432
|
+
*
|
|
433
|
+
* Fusion and SolidWorks zoom to the cursor and most people expect it — you
|
|
434
|
+
* point at the corner you want and lean in. It is not universally liked: on a
|
|
435
|
+
* trackpad it can walk the model off screen, which is why the other one
|
|
436
|
+
* stays.
|
|
437
|
+
*/
|
|
438
|
+
zoomTo?: 'cursor' | 'centre';
|
|
371
439
|
}
|
|
372
440
|
/**
|
|
373
441
|
* Mounts `camera-controls` against the R3F camera and canvas.
|
|
@@ -378,7 +446,7 @@ interface CadCameraControlsProps {
|
|
|
378
446
|
* also registered as R3F's default `controls`, which is how anything else in
|
|
379
447
|
* the scene reaches the orbit target.
|
|
380
448
|
*/
|
|
381
|
-
declare const CadCameraControls: ({ controlsRef, scheme, freeOrbit, }: CadCameraControlsProps) => null;
|
|
449
|
+
declare const CadCameraControls: ({ controlsRef, scheme, freeOrbit, zoomTo, }: CadCameraControlsProps) => null;
|
|
382
450
|
|
|
383
451
|
interface ViewerControls {
|
|
384
452
|
/** Frames the part without changing the current viewing direction. */
|
|
@@ -430,6 +498,20 @@ interface ViewerProps {
|
|
|
430
498
|
controls?: ControlScheme;
|
|
431
499
|
/** Orbit past the poles instead of stopping there. On by default. */
|
|
432
500
|
freeOrbit?: boolean;
|
|
501
|
+
/**
|
|
502
|
+
* What the wheel zooms toward: the pointer, or the middle of the view.
|
|
503
|
+
*
|
|
504
|
+
* `cursor` by default, which is what Fusion does and what most people reach
|
|
505
|
+
* for. It is a preference rather than a right answer — on a trackpad it can
|
|
506
|
+
* walk the model off screen.
|
|
507
|
+
*/
|
|
508
|
+
zoomTo?: 'cursor' | 'centre';
|
|
509
|
+
/**
|
|
510
|
+
* Whether a double **middle** click re-frames the part. On by default — it is
|
|
511
|
+
* the way back from having zoomed into a corner, which zooming to the cursor
|
|
512
|
+
* makes easy to do.
|
|
513
|
+
*/
|
|
514
|
+
recentreOnDoubleClick?: boolean;
|
|
433
515
|
/** Lighting and background. The part's own colours are tuned against this rig. */
|
|
434
516
|
theme?: Partial<ViewerTheme>;
|
|
435
517
|
/**
|
|
@@ -602,4 +684,4 @@ declare function bestOwner(model: PartModel, owners: readonly FeatureTag[], cont
|
|
|
602
684
|
*/
|
|
603
685
|
declare function cycleOwner(owners: readonly FeatureTag[], current: FeatureTag | null): FeatureTag | null;
|
|
604
686
|
|
|
605
|
-
export { type ArrowPlacement, Axes, type AxesProps, CHAMFER, CadCameraControls, type CadCameraControlsProps, type ControlScheme, type CubeZone, DirectionArrows, type DirectionArrowsProps, type DirectionGroup, ExtendedCameraControls, type ExtendedCameraControlsOptions, FEATURE_TYPE_RANKS, FeatureTag, FeatureType, Grid, type GridProps, type GridSpec, type NamedDirection, PartModel, PartModelFeature, PartModelRegion, PartReportFormatError, Projection, type RankingContext, RegionIndex, type SurfaceOf, TAP_SLOP, type TapPoint, type TapTracker, TriangleRange, UnsupportedKernelVersionError, VIEW_NAMES, VIEW_SIGNS, Vec3, ViewCube, type ViewCubeProps, type ViewKind, type ViewName, Viewer, ViewerCamera, type ViewerControls, type ViewerHandle, type ViewerProps, ViewerTheme, ViewerView, arrowPlacement, bestOwner, buildRegionIndex, cubeOutlineGeometry, cubeZones, cycleOwner, directionIndexOf, directionLabel, featureTypeRank, gridGeometry, gridSpec, groupByDirection, labelGeometry, labelTexture, movedFar, panelGeometry, rankOwners, regionEdgesGeometry, regionNormals, sameDirection, trackTaps, useContentBox, useTapGuard, useViewerControls, viewKind, viewUp, viewVector, visualSurfaces };
|
|
687
|
+
export { type ArrowPlacement, Axes, type AxesProps, CHAMFER, CadCameraControls, type CadCameraControlsProps, type ControlScheme, type CubeZone, DOUBLE_TAP_MS, DirectionArrows, type DirectionArrowsProps, type DirectionGroup, type DoubleTapPoint, type DoubleTapTracker, ExtendedCameraControls, type ExtendedCameraControlsOptions, FEATURE_TYPE_RANKS, FeatureTag, FeatureType, Grid, type GridProps, type GridSpec, type NamedDirection, PartModel, PartModelFeature, PartModelRegion, PartReportFormatError, Projection, type RankingContext, RegionIndex, type SurfaceOf, TAP_SLOP, type TapPoint, type TapTracker, TriangleRange, UnsupportedKernelVersionError, VIEW_NAMES, VIEW_SIGNS, Vec3, ViewCube, type ViewCubeProps, type ViewKind, type ViewName, Viewer, ViewerCamera, type ViewerControls, type ViewerHandle, type ViewerProps, ViewerTheme, ViewerView, arrowPlacement, bestOwner, buildRegionIndex, cubeOutlineGeometry, cubeZones, cycleOwner, directionIndexOf, directionLabel, featureTypeRank, gridGeometry, gridSpec, groupByDirection, labelGeometry, labelTexture, movedFar, panelGeometry, rankOwners, regionAdjacency, regionEdgesGeometry, regionNormals, sameDirection, squaredUp, trackDoubleTaps, trackTaps, useContentBox, useTapGuard, useViewerControls, viewKind, viewUp, viewVector, visualSurfaces };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CAD_CAMERA_UP,
|
|
3
3
|
CANDIDATE_WEIGHT,
|
|
4
|
+
CHAMFER,
|
|
4
5
|
CONE_AXIS,
|
|
5
6
|
CadCameraControls,
|
|
6
7
|
DEFAULT_FIT_MARGIN,
|
|
7
8
|
DEFAULT_THEME,
|
|
8
9
|
DIRECTION_COLORS,
|
|
10
|
+
DOUBLE_TAP_MS,
|
|
9
11
|
EXCLUDE_FROM_FRAME,
|
|
10
12
|
EnginePart,
|
|
11
13
|
ExtendedCameraControls,
|
|
@@ -27,6 +29,8 @@ import {
|
|
|
27
29
|
SectionView,
|
|
28
30
|
TAP_SLOP,
|
|
29
31
|
UnsupportedKernelVersionError,
|
|
32
|
+
VIEW_NAMES,
|
|
33
|
+
VIEW_SIGNS,
|
|
30
34
|
Viewer,
|
|
31
35
|
applyHighlightLayers,
|
|
32
36
|
applyProjection,
|
|
@@ -41,6 +45,8 @@ import {
|
|
|
41
45
|
cadViewDirections,
|
|
42
46
|
contentBounds,
|
|
43
47
|
createPart,
|
|
48
|
+
cubeOutlineGeometry,
|
|
49
|
+
cubeZones,
|
|
44
50
|
currentViewDirection,
|
|
45
51
|
cycleOwner,
|
|
46
52
|
defaultBounds,
|
|
@@ -52,12 +58,16 @@ import {
|
|
|
52
58
|
fitDistance,
|
|
53
59
|
focusForPick,
|
|
54
60
|
groupByDirection,
|
|
61
|
+
labelGeometry,
|
|
62
|
+
labelTexture,
|
|
55
63
|
movedFar,
|
|
56
64
|
normalizePartReport,
|
|
57
65
|
orthographicHalfHeight,
|
|
66
|
+
panelGeometry,
|
|
58
67
|
perspectiveFitDistance,
|
|
59
68
|
pickedStartDepth,
|
|
60
69
|
rankOwners,
|
|
70
|
+
regionAdjacency,
|
|
61
71
|
regionEdgesGeometry,
|
|
62
72
|
resolveSectionPlane,
|
|
63
73
|
resolveTheme,
|
|
@@ -72,15 +82,20 @@ import {
|
|
|
72
82
|
sectionOffset,
|
|
73
83
|
sectionPlane,
|
|
74
84
|
smoothRegionNormals,
|
|
85
|
+
squaredUp,
|
|
75
86
|
startPosition,
|
|
76
87
|
themesEqual,
|
|
88
|
+
trackDoubleTaps,
|
|
77
89
|
trackTaps,
|
|
78
90
|
useContentBox,
|
|
79
91
|
useTapGuard,
|
|
80
92
|
useViewerControls,
|
|
81
93
|
viewDirection,
|
|
94
|
+
viewKind,
|
|
95
|
+
viewUp,
|
|
96
|
+
viewVector,
|
|
82
97
|
visualSurfaces
|
|
83
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-ILZ2KQUK.js";
|
|
84
99
|
|
|
85
100
|
// src/primitives.tsx
|
|
86
101
|
import { GizmoHelper } from "@react-three/drei";
|
|
@@ -125,233 +140,6 @@ function gridGeometry(spec) {
|
|
|
125
140
|
return geometry;
|
|
126
141
|
}
|
|
127
142
|
|
|
128
|
-
// src/render/view-cube.ts
|
|
129
|
-
import {
|
|
130
|
-
BufferGeometry as BufferGeometry2,
|
|
131
|
-
CanvasTexture,
|
|
132
|
-
Float32BufferAttribute as Float32BufferAttribute2,
|
|
133
|
-
SRGBColorSpace,
|
|
134
|
-
Vector3 as Vector32
|
|
135
|
-
} from "three";
|
|
136
|
-
var VIEW_NAMES = [
|
|
137
|
-
// The six faces.
|
|
138
|
-
"top",
|
|
139
|
-
"bottom",
|
|
140
|
-
"front",
|
|
141
|
-
"back",
|
|
142
|
-
"left",
|
|
143
|
-
"right",
|
|
144
|
-
// The twelve edges.
|
|
145
|
-
"top-front",
|
|
146
|
-
"top-back",
|
|
147
|
-
"top-left",
|
|
148
|
-
"top-right",
|
|
149
|
-
"bottom-front",
|
|
150
|
-
"bottom-back",
|
|
151
|
-
"bottom-left",
|
|
152
|
-
"bottom-right",
|
|
153
|
-
"front-left",
|
|
154
|
-
"front-right",
|
|
155
|
-
"back-left",
|
|
156
|
-
"back-right",
|
|
157
|
-
// The eight corners.
|
|
158
|
-
"top-front-left",
|
|
159
|
-
"top-front-right",
|
|
160
|
-
"top-back-left",
|
|
161
|
-
"top-back-right",
|
|
162
|
-
"bottom-front-left",
|
|
163
|
-
"bottom-front-right",
|
|
164
|
-
"bottom-back-left",
|
|
165
|
-
"bottom-back-right"
|
|
166
|
-
];
|
|
167
|
-
var VIEW_SIGNS = {
|
|
168
|
-
top: [0, 0, 1],
|
|
169
|
-
bottom: [0, 0, -1],
|
|
170
|
-
front: [0, -1, 0],
|
|
171
|
-
back: [0, 1, 0],
|
|
172
|
-
left: [-1, 0, 0],
|
|
173
|
-
right: [1, 0, 0],
|
|
174
|
-
"top-front": [0, -1, 1],
|
|
175
|
-
"top-back": [0, 1, 1],
|
|
176
|
-
"top-left": [-1, 0, 1],
|
|
177
|
-
"top-right": [1, 0, 1],
|
|
178
|
-
"bottom-front": [0, -1, -1],
|
|
179
|
-
"bottom-back": [0, 1, -1],
|
|
180
|
-
"bottom-left": [-1, 0, -1],
|
|
181
|
-
"bottom-right": [1, 0, -1],
|
|
182
|
-
"front-left": [-1, -1, 0],
|
|
183
|
-
"front-right": [1, -1, 0],
|
|
184
|
-
"back-left": [-1, 1, 0],
|
|
185
|
-
"back-right": [1, 1, 0],
|
|
186
|
-
"top-front-left": [-1, -1, 1],
|
|
187
|
-
"top-front-right": [1, -1, 1],
|
|
188
|
-
"top-back-left": [-1, 1, 1],
|
|
189
|
-
"top-back-right": [1, 1, 1],
|
|
190
|
-
"bottom-front-left": [-1, -1, -1],
|
|
191
|
-
"bottom-front-right": [1, -1, -1],
|
|
192
|
-
"bottom-back-left": [-1, 1, -1],
|
|
193
|
-
"bottom-back-right": [1, 1, -1]
|
|
194
|
-
};
|
|
195
|
-
function viewKind(name) {
|
|
196
|
-
const off = VIEW_SIGNS[name].filter((sign) => sign !== 0).length;
|
|
197
|
-
if (off === 1) return "face";
|
|
198
|
-
if (off === 2) return "edge";
|
|
199
|
-
return "corner";
|
|
200
|
-
}
|
|
201
|
-
var DIRECTIONS = new Map(
|
|
202
|
-
VIEW_NAMES.map((name) => {
|
|
203
|
-
const [x, y, z] = VIEW_SIGNS[name];
|
|
204
|
-
const length = Math.hypot(x, y, z);
|
|
205
|
-
return [name, { x: x / length, y: y / length, z: z / length }];
|
|
206
|
-
})
|
|
207
|
-
);
|
|
208
|
-
function viewVector(name) {
|
|
209
|
-
return DIRECTIONS.get(name) ?? { x: 0, y: 0, z: 1 };
|
|
210
|
-
}
|
|
211
|
-
function viewUp(direction) {
|
|
212
|
-
if (direction.x === 0 && direction.y === 0) {
|
|
213
|
-
return { x: 0, y: direction.z > 0 ? 1 : -1, z: 0 };
|
|
214
|
-
}
|
|
215
|
-
return { x: 0, y: 0, z: 1 };
|
|
216
|
-
}
|
|
217
|
-
var CHAMFER = 0.5834;
|
|
218
|
-
function vec(v) {
|
|
219
|
-
return { x: v.x, y: v.y, z: v.z };
|
|
220
|
-
}
|
|
221
|
-
function cubeZones(chamfer = CHAMFER) {
|
|
222
|
-
const AXES = [0, 1, 2];
|
|
223
|
-
return VIEW_NAMES.map((name) => {
|
|
224
|
-
const kind = viewKind(name);
|
|
225
|
-
const direction = viewVector(name);
|
|
226
|
-
const [sx, sy, sz] = VIEW_SIGNS[name];
|
|
227
|
-
const sign = (axis) => VIEW_SIGNS[name][axis] ?? 0;
|
|
228
|
-
const normal = new Vector32(direction.x, direction.y, direction.z);
|
|
229
|
-
let polygon;
|
|
230
|
-
if (kind === "face") {
|
|
231
|
-
const up = viewUp(direction);
|
|
232
|
-
const upVector = new Vector32(up.x, up.y, up.z);
|
|
233
|
-
const right = normal.clone().negate().cross(upVector).normalize();
|
|
234
|
-
const square = [
|
|
235
|
-
[-1, -1],
|
|
236
|
-
[1, -1],
|
|
237
|
-
[1, 1],
|
|
238
|
-
[-1, 1]
|
|
239
|
-
];
|
|
240
|
-
polygon = square.map(
|
|
241
|
-
([u, v]) => normal.clone().addScaledVector(right, u * chamfer).addScaledVector(upVector, v * chamfer)
|
|
242
|
-
);
|
|
243
|
-
} else if (kind === "edge") {
|
|
244
|
-
const a = AXES.find((axis) => sign(axis) !== 0) ?? 0;
|
|
245
|
-
const b = [...AXES].reverse().find((axis) => sign(axis) !== 0) ?? 0;
|
|
246
|
-
const c = AXES.find((axis) => sign(axis) === 0) ?? 0;
|
|
247
|
-
const rectangle = [
|
|
248
|
-
[1, chamfer, -chamfer],
|
|
249
|
-
[1, chamfer, chamfer],
|
|
250
|
-
[chamfer, 1, chamfer],
|
|
251
|
-
[chamfer, 1, -chamfer]
|
|
252
|
-
];
|
|
253
|
-
polygon = rectangle.map(
|
|
254
|
-
([onA, onB, onC]) => new Vector32().setComponent(a, sign(a) * onA).setComponent(b, sign(b) * onB).setComponent(c, onC)
|
|
255
|
-
);
|
|
256
|
-
} else {
|
|
257
|
-
const triangle = [
|
|
258
|
-
[1, chamfer, chamfer],
|
|
259
|
-
[chamfer, 1, chamfer],
|
|
260
|
-
[chamfer, chamfer, 1]
|
|
261
|
-
];
|
|
262
|
-
polygon = triangle.map(([onX, onY, onZ]) => new Vector32(sx * onX, sy * onY, sz * onZ));
|
|
263
|
-
}
|
|
264
|
-
const [first, second, third] = polygon;
|
|
265
|
-
if (first && second && third) {
|
|
266
|
-
const facing = new Vector32().subVectors(second, first).cross(new Vector32().subVectors(third, first));
|
|
267
|
-
if (facing.dot(normal) < 0) polygon.reverse();
|
|
268
|
-
}
|
|
269
|
-
return { name, kind, direction, polygon: polygon.map(vec) };
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
function panelGeometry(zone) {
|
|
273
|
-
const positions = [];
|
|
274
|
-
const normals = [];
|
|
275
|
-
const [first] = zone.polygon;
|
|
276
|
-
const geometry = new BufferGeometry2();
|
|
277
|
-
if (!first) return geometry;
|
|
278
|
-
for (let index = 1; index + 1 < zone.polygon.length; index += 1) {
|
|
279
|
-
const b = zone.polygon[index];
|
|
280
|
-
const c = zone.polygon[index + 1];
|
|
281
|
-
if (!b || !c) continue;
|
|
282
|
-
positions.push(first.x, first.y, first.z, b.x, b.y, b.z, c.x, c.y, c.z);
|
|
283
|
-
for (let vertex = 0; vertex < 3; vertex += 1) {
|
|
284
|
-
normals.push(zone.direction.x, zone.direction.y, zone.direction.z);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
geometry.setAttribute("position", new Float32BufferAttribute2(positions, 3));
|
|
288
|
-
geometry.setAttribute("normal", new Float32BufferAttribute2(normals, 3));
|
|
289
|
-
return geometry;
|
|
290
|
-
}
|
|
291
|
-
function cubeOutlineGeometry(zones) {
|
|
292
|
-
const positions = [];
|
|
293
|
-
for (const zone of zones) {
|
|
294
|
-
for (let index = 0; index < zone.polygon.length; index += 1) {
|
|
295
|
-
const from = zone.polygon[index];
|
|
296
|
-
const to = zone.polygon[(index + 1) % zone.polygon.length];
|
|
297
|
-
if (!from || !to) continue;
|
|
298
|
-
positions.push(from.x, from.y, from.z, to.x, to.y, to.z);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
const geometry = new BufferGeometry2();
|
|
302
|
-
geometry.setAttribute("position", new Float32BufferAttribute2(positions, 3));
|
|
303
|
-
return geometry;
|
|
304
|
-
}
|
|
305
|
-
function labelGeometry(zone) {
|
|
306
|
-
const positions = [];
|
|
307
|
-
const uvs = [];
|
|
308
|
-
const corners = [0, 1, 2, 0, 2, 3];
|
|
309
|
-
const corner = [
|
|
310
|
-
[0, 0],
|
|
311
|
-
[1, 0],
|
|
312
|
-
[1, 1],
|
|
313
|
-
[0, 1]
|
|
314
|
-
];
|
|
315
|
-
for (const index of corners) {
|
|
316
|
-
const point = zone.polygon[index];
|
|
317
|
-
const uv = corner[index];
|
|
318
|
-
if (!point || !uv) continue;
|
|
319
|
-
positions.push(
|
|
320
|
-
point.x + zone.direction.x * 4e-3,
|
|
321
|
-
point.y + zone.direction.y * 4e-3,
|
|
322
|
-
point.z + zone.direction.z * 4e-3
|
|
323
|
-
);
|
|
324
|
-
uvs.push(uv[0] ?? 0, uv[1] ?? 0);
|
|
325
|
-
}
|
|
326
|
-
const geometry = new BufferGeometry2();
|
|
327
|
-
geometry.setAttribute("position", new Float32BufferAttribute2(positions, 3));
|
|
328
|
-
geometry.setAttribute("uv", new Float32BufferAttribute2(uvs, 2));
|
|
329
|
-
return geometry;
|
|
330
|
-
}
|
|
331
|
-
function labelTexture(label, color) {
|
|
332
|
-
const size = 128;
|
|
333
|
-
const canvas = document.createElement("canvas");
|
|
334
|
-
canvas.width = size;
|
|
335
|
-
canvas.height = size;
|
|
336
|
-
const context = canvas.getContext("2d");
|
|
337
|
-
if (context) {
|
|
338
|
-
const text = label.toUpperCase();
|
|
339
|
-
const hex = `#${color.toString(16).padStart(6, "0")}`;
|
|
340
|
-
context.font = `600 ${size / 4}px system-ui, sans-serif`;
|
|
341
|
-
const width = context.measureText("BOTTOM").width || 1;
|
|
342
|
-
const scale = Math.min(1, size * 0.78 / width);
|
|
343
|
-
context.font = `600 ${size / 4 * scale}px system-ui, sans-serif`;
|
|
344
|
-
context.textAlign = "center";
|
|
345
|
-
context.textBaseline = "middle";
|
|
346
|
-
context.fillStyle = hex;
|
|
347
|
-
context.fillText(text, size / 2, size / 2);
|
|
348
|
-
}
|
|
349
|
-
const texture = new CanvasTexture(canvas);
|
|
350
|
-
texture.colorSpace = SRGBColorSpace;
|
|
351
|
-
texture.needsUpdate = true;
|
|
352
|
-
return texture;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
143
|
// src/primitives.tsx
|
|
356
144
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
357
145
|
var FURNITURE = { [EXCLUDE_FROM_FRAME]: true };
|
|
@@ -460,7 +248,7 @@ var CubePanels = ({
|
|
|
460
248
|
// src/direction-arrows.tsx
|
|
461
249
|
import { useThree as useThree2 } from "@react-three/fiber";
|
|
462
250
|
import { useMemo as useMemo2 } from "react";
|
|
463
|
-
import { Quaternion, Vector3 as
|
|
251
|
+
import { Quaternion, Vector3 as Vector32 } from "three";
|
|
464
252
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
465
253
|
var FURNITURE2 = { [EXCLUDE_FROM_FRAME]: true };
|
|
466
254
|
var DirectionArrows = ({
|
|
@@ -476,6 +264,11 @@ var DirectionArrows = ({
|
|
|
476
264
|
const box = useContentBox();
|
|
477
265
|
const resolved = useMemo2(() => resolveTheme(theme), [theme]);
|
|
478
266
|
const shown = shownDirection === void 0 ? activeDirection : shownDirection;
|
|
267
|
+
const drawn = (index) => {
|
|
268
|
+
if (shown === null) return true;
|
|
269
|
+
if (typeof shown === "number") return shown === index;
|
|
270
|
+
return shown.includes(index);
|
|
271
|
+
};
|
|
479
272
|
if (!visible) return null;
|
|
480
273
|
return (
|
|
481
274
|
// Excluded from framing: the arrows are deliberately placed outside the
|
|
@@ -483,7 +276,7 @@ var DirectionArrows = ({
|
|
|
483
276
|
// part small in the middle of them.
|
|
484
277
|
/* @__PURE__ */ jsxs2("group", { userData: FURNITURE2, children: [
|
|
485
278
|
directions.map((direction, index) => {
|
|
486
|
-
if (
|
|
279
|
+
if (!drawn(index)) return null;
|
|
487
280
|
return /* @__PURE__ */ jsx2(
|
|
488
281
|
Arrow,
|
|
489
282
|
{
|
|
@@ -517,7 +310,7 @@ var Arrow = ({ direction, box, color, opacity, onPick, onTop = false }) => {
|
|
|
517
310
|
const placement = arrowPlacement(direction, box);
|
|
518
311
|
const aim = new Quaternion().setFromUnitVectors(
|
|
519
312
|
CONE_AXIS,
|
|
520
|
-
new
|
|
313
|
+
new Vector32(direction.x, direction.y, direction.z).normalize()
|
|
521
314
|
);
|
|
522
315
|
return { tip: placement.tip, length: placement.length, quaternion: aim };
|
|
523
316
|
}, [box, direction]);
|
|
@@ -584,6 +377,7 @@ export {
|
|
|
584
377
|
DEFAULT_FIT_MARGIN,
|
|
585
378
|
DEFAULT_THEME,
|
|
586
379
|
DIRECTION_COLORS,
|
|
380
|
+
DOUBLE_TAP_MS,
|
|
587
381
|
DirectionArrows,
|
|
588
382
|
EXCLUDE_FROM_FRAME,
|
|
589
383
|
EnginePart,
|
|
@@ -645,6 +439,7 @@ export {
|
|
|
645
439
|
perspectiveFitDistance,
|
|
646
440
|
pickedStartDepth,
|
|
647
441
|
rankOwners,
|
|
442
|
+
regionAdjacency,
|
|
648
443
|
regionEdgesGeometry,
|
|
649
444
|
regionNormals,
|
|
650
445
|
resolveSectionPlane,
|
|
@@ -660,8 +455,10 @@ export {
|
|
|
660
455
|
sectionOffset,
|
|
661
456
|
sectionPlane,
|
|
662
457
|
smoothRegionNormals,
|
|
458
|
+
squaredUp,
|
|
663
459
|
startPosition,
|
|
664
460
|
themesEqual,
|
|
461
|
+
trackDoubleTaps,
|
|
665
462
|
trackTaps,
|
|
666
463
|
useContentBox,
|
|
667
464
|
useTapGuard,
|
|
@@ -215,7 +215,7 @@ declare const HIGHLIGHT_COLORS: {
|
|
|
215
215
|
* of the palette — it is an identity, not a ranking, which is why the colors
|
|
216
216
|
* are unordered and deliberately not a scale.
|
|
217
217
|
*/
|
|
218
|
-
declare const DIRECTION_COLORS: readonly [3900150,
|
|
218
|
+
declare const DIRECTION_COLORS: readonly [3900150, 889992, 14239471, 6809849, 6660877, 15485081, 9741240, 4906624, 1981066];
|
|
219
219
|
declare const DEFAULT_THEME: ViewerTheme;
|
|
220
220
|
declare function resolveTheme(overrides?: Partial<ViewerTheme>): ViewerTheme;
|
|
221
221
|
/**
|
|
@@ -303,11 +303,15 @@ declare function buildRegionAttribute(model: RegionTable, texels: Map<number, nu
|
|
|
303
303
|
/**
|
|
304
304
|
* Builds the renderable part.
|
|
305
305
|
*
|
|
306
|
-
* Takes
|
|
306
|
+
* Takes working use of `geometry`: it adds {@link REGION_ATTRIBUTE} to it and
|
|
307
307
|
* removes that again on dispose, but never disposes the geometry itself — the
|
|
308
308
|
* loader's caller owns it, and a viewer destroying an object it was handed is a
|
|
309
|
-
* good way to break a cache that is legitimately sharing it.
|
|
310
|
-
*
|
|
309
|
+
* good way to break a cache that is legitimately sharing it.
|
|
310
|
+
*
|
|
311
|
+
* Two parts on one geometry is still not a thing to *render*, but it is a state
|
|
312
|
+
* that happens: a report changing identity rebuilds the part against the same
|
|
313
|
+
* cached mesh, and for a moment both exist. So dispose removes the attribute
|
|
314
|
+
* only if it is still the one this part set — see the note where it is built.
|
|
311
315
|
*/
|
|
312
316
|
declare function createPart(model: PartModel, geometry: BufferGeometry, theme: ViewerTheme): PartObject;
|
|
313
317
|
|
|
@@ -772,6 +776,15 @@ interface PartMeshProps {
|
|
|
772
776
|
* real change, so echoing it into state is safe.
|
|
773
777
|
*/
|
|
774
778
|
onSectionChange?: (state: SectionState) => void;
|
|
779
|
+
/**
|
|
780
|
+
* Which faces touch which, once the mesh is in.
|
|
781
|
+
*
|
|
782
|
+
* The consumer cannot work this out: it has a region table with areas and
|
|
783
|
+
* shape kinds, and the topology only exists in the geometry. Handed over
|
|
784
|
+
* rather than queried, because it is computed once per mesh and the consumer
|
|
785
|
+
* needs it to answer questions about faces it has not clicked yet.
|
|
786
|
+
*/
|
|
787
|
+
onAdjacency?: (adjacency: ReadonlyMap<number, ReadonlySet<number>>) => void;
|
|
775
788
|
/**
|
|
776
789
|
* A feature to frame. Framed when it changes, so setting it to the feature
|
|
777
790
|
* already framed does nothing — a zoom is a request, not a state to hold.
|
|
@@ -801,7 +814,7 @@ interface PartMeshProps {
|
|
|
801
814
|
* React render at all: the hovered face lives in a ref, and routing it through
|
|
802
815
|
* state is what this rewrite exists to stop doing.
|
|
803
816
|
*/
|
|
804
|
-
declare const PartMesh: ({ model, geometry, selection, candidates, highlights, regionHighlights, pickedRegions, hoveredFeatureIds, activeDirection, section, onSectionChange, focusFeature, onHover, onPick, theme, showEdges, }: PartMeshProps) => react.JSX.Element;
|
|
817
|
+
declare const PartMesh: ({ model, geometry, selection, candidates, highlights, regionHighlights, pickedRegions, hoveredFeatureIds, activeDirection, section, onSectionChange, onAdjacency, focusFeature, onHover, onPick, theme, showEdges, }: PartMeshProps) => react.JSX.Element;
|
|
805
818
|
|
|
806
819
|
interface EnginePartProps extends Omit<PartMeshProps, 'model' | 'geometry'> {
|
|
807
820
|
/**
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toolpath/viewer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "React Three Fiber viewer for Toolpath Engine part reports",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "https://github.com/toolpath/
|
|
8
|
+
"url": "https://github.com/toolpath/ui-packages.git",
|
|
9
9
|
"directory": "packages/viewer"
|
|
10
10
|
},
|
|
11
11
|
"homepage": "https://developers.toolpath.com",
|
|
12
12
|
"bugs": {
|
|
13
|
-
"url": "https://github.com/toolpath/
|
|
13
|
+
"url": "https://github.com/toolpath/ui-packages/issues"
|
|
14
14
|
},
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public",
|