@cadview/core 0.1.0 → 0.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.
- package/README.md +36 -3
- package/dist/index.cjs +101 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -1
- package/dist/index.d.ts +57 -1
- package/dist/index.js +101 -10
- package/dist/index.js.map +1 -1
- package/package.json +12 -25
package/dist/index.d.cts
CHANGED
|
@@ -359,6 +359,24 @@ declare class EventEmitter<T extends Record<string, any> = Record<string, any>>
|
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
type Tool = 'pan' | 'select' | 'measure';
|
|
362
|
+
/**
|
|
363
|
+
* Interface for registering custom file format converters.
|
|
364
|
+
* Converters are checked in order during `loadFile()` and `loadBuffer()`.
|
|
365
|
+
* The first converter whose `detect()` returns true will be used.
|
|
366
|
+
*/
|
|
367
|
+
interface FormatConverter {
|
|
368
|
+
/**
|
|
369
|
+
* Return true if the buffer is in this format.
|
|
370
|
+
* Implementations should check magic bytes, not file extensions.
|
|
371
|
+
* Must not throw — return false on any error.
|
|
372
|
+
*/
|
|
373
|
+
detect(buffer: ArrayBuffer): boolean;
|
|
374
|
+
/**
|
|
375
|
+
* Convert the buffer to a DXF string.
|
|
376
|
+
* The returned string must be valid DXF parseable by `parseDxf()`.
|
|
377
|
+
*/
|
|
378
|
+
convert(buffer: ArrayBuffer): Promise<string>;
|
|
379
|
+
}
|
|
362
380
|
interface CadViewerOptions {
|
|
363
381
|
theme?: Theme;
|
|
364
382
|
backgroundColor?: string;
|
|
@@ -367,6 +385,8 @@ interface CadViewerOptions {
|
|
|
367
385
|
maxZoom?: number;
|
|
368
386
|
zoomSpeed?: number;
|
|
369
387
|
initialTool?: Tool;
|
|
388
|
+
/** Format converters for non-DXF file formats (e.g. DWG via @cadview/dwg). */
|
|
389
|
+
formatConverters?: FormatConverter[];
|
|
370
390
|
}
|
|
371
391
|
declare class CadViewer {
|
|
372
392
|
private canvas;
|
|
@@ -381,14 +401,50 @@ declare class CadViewer {
|
|
|
381
401
|
private currentTool;
|
|
382
402
|
private inputHandler;
|
|
383
403
|
private resizeObserver;
|
|
404
|
+
private formatConverters;
|
|
384
405
|
private selectedEntityIndex;
|
|
385
406
|
private renderPending;
|
|
386
407
|
private destroyed;
|
|
408
|
+
private loadGeneration;
|
|
387
409
|
private mouseScreenX;
|
|
388
410
|
private mouseScreenY;
|
|
389
411
|
constructor(canvas: HTMLCanvasElement, options?: CadViewerOptions);
|
|
412
|
+
/**
|
|
413
|
+
* Throws if the viewer has been destroyed.
|
|
414
|
+
* Call at the start of any public method that mutates state.
|
|
415
|
+
*/
|
|
416
|
+
private guardDestroyed;
|
|
417
|
+
/**
|
|
418
|
+
* Run registered format converters on a buffer.
|
|
419
|
+
* Returns the converted DXF string if a converter matched, or null otherwise.
|
|
420
|
+
* Each converter's detect() is wrapped in try/catch — a throwing detect() is skipped.
|
|
421
|
+
*/
|
|
422
|
+
private runConverters;
|
|
423
|
+
/**
|
|
424
|
+
* Load a CAD file from a browser File object.
|
|
425
|
+
* Automatically detects the format using registered converters (e.g. DWG).
|
|
426
|
+
* Falls back to DXF parsing if no converter matches.
|
|
427
|
+
*/
|
|
390
428
|
loadFile(file: File): Promise<void>;
|
|
429
|
+
/**
|
|
430
|
+
* Load a CAD file from an ArrayBuffer with format converter support.
|
|
431
|
+
* Unlike `loadArrayBuffer()` (sync, DXF-only), this method is async and
|
|
432
|
+
* checks registered FormatConverters for non-DXF formats.
|
|
433
|
+
*/
|
|
434
|
+
loadBuffer(buffer: ArrayBuffer): Promise<void>;
|
|
435
|
+
/**
|
|
436
|
+
* Load a pre-parsed DxfDocument directly, bypassing the parser.
|
|
437
|
+
* Useful for custom parsers or pre-processed documents.
|
|
438
|
+
*/
|
|
439
|
+
loadDocument(doc: DxfDocument): void;
|
|
440
|
+
/**
|
|
441
|
+
* Load a DXF string directly (synchronous, no format conversion).
|
|
442
|
+
*/
|
|
391
443
|
loadString(dxf: string): void;
|
|
444
|
+
/**
|
|
445
|
+
* Load a DXF file from an ArrayBuffer (synchronous, no format conversion).
|
|
446
|
+
* For format conversion support (e.g. DWG), use `loadFile()` or `loadBuffer()` instead.
|
|
447
|
+
*/
|
|
392
448
|
loadArrayBuffer(buffer: ArrayBuffer): void;
|
|
393
449
|
/**
|
|
394
450
|
* Clear the current document and reset all state without destroying the viewer.
|
|
@@ -507,4 +563,4 @@ interface BBox {
|
|
|
507
563
|
declare function computeEntitiesBounds(entities: DxfEntity[]): BBox | null;
|
|
508
564
|
declare function computeEntityBBox(entity: DxfEntity): BBox | null;
|
|
509
565
|
|
|
510
|
-
export { type BBox, CadViewer, type CadViewerEventMap, type CadViewerOptions, Camera, CanvasRenderer, type DxfArcEntity, type DxfAttrib, type DxfBlock, type DxfCircleEntity, type DxfDimensionEntity, type DxfDocument, type DxfEllipseEntity, type DxfEntity, type DxfEntityBase, type DxfHatchBoundaryPath, type DxfHatchEdge, type DxfHatchEntity, type DxfHeader, type DxfInsertEntity, type DxfLayer, type DxfLineEntity, type DxfLineType, type DxfLwPolylineEntity, type DxfLwPolylineVertex, type DxfMTextEntity, DxfParseError, type DxfPointEntity, type DxfPolylineEntity, type DxfSplineEntity, type DxfStyle, type DxfTextEntity, EventEmitter, LayerManager, type MeasureEvent, type MeasureState, MeasureTool, type Point2D, type Point3D, type SelectEvent, type SnapResult, type SnapType, SpatialIndex, THEMES, type Theme, type ThemeConfig, type Tool, type ViewTransform, aciToDisplayColor, aciToHex, applyTransform, computeEntitiesBounds, computeEntityBBox, drawEntity, findSnaps, fitToView, hitTest, parseDxf, renderMeasureOverlay, resolveEntityColor, screenToWorld, trueColorToHex, worldToScreen, zoomAtPoint };
|
|
566
|
+
export { type BBox, CadViewer, type CadViewerEventMap, type CadViewerOptions, Camera, CanvasRenderer, type DxfArcEntity, type DxfAttrib, type DxfBlock, type DxfCircleEntity, type DxfDimensionEntity, type DxfDocument, type DxfEllipseEntity, type DxfEntity, type DxfEntityBase, type DxfHatchBoundaryPath, type DxfHatchEdge, type DxfHatchEntity, type DxfHeader, type DxfInsertEntity, type DxfLayer, type DxfLineEntity, type DxfLineType, type DxfLwPolylineEntity, type DxfLwPolylineVertex, type DxfMTextEntity, DxfParseError, type DxfPointEntity, type DxfPolylineEntity, type DxfSplineEntity, type DxfStyle, type DxfTextEntity, EventEmitter, type FormatConverter, LayerManager, type MeasureEvent, type MeasureState, MeasureTool, type Point2D, type Point3D, type SelectEvent, type SnapResult, type SnapType, SpatialIndex, THEMES, type Theme, type ThemeConfig, type Tool, type ViewTransform, aciToDisplayColor, aciToHex, applyTransform, computeEntitiesBounds, computeEntityBBox, drawEntity, findSnaps, fitToView, hitTest, parseDxf, renderMeasureOverlay, resolveEntityColor, screenToWorld, trueColorToHex, worldToScreen, zoomAtPoint };
|
package/dist/index.d.ts
CHANGED
|
@@ -359,6 +359,24 @@ declare class EventEmitter<T extends Record<string, any> = Record<string, any>>
|
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
type Tool = 'pan' | 'select' | 'measure';
|
|
362
|
+
/**
|
|
363
|
+
* Interface for registering custom file format converters.
|
|
364
|
+
* Converters are checked in order during `loadFile()` and `loadBuffer()`.
|
|
365
|
+
* The first converter whose `detect()` returns true will be used.
|
|
366
|
+
*/
|
|
367
|
+
interface FormatConverter {
|
|
368
|
+
/**
|
|
369
|
+
* Return true if the buffer is in this format.
|
|
370
|
+
* Implementations should check magic bytes, not file extensions.
|
|
371
|
+
* Must not throw — return false on any error.
|
|
372
|
+
*/
|
|
373
|
+
detect(buffer: ArrayBuffer): boolean;
|
|
374
|
+
/**
|
|
375
|
+
* Convert the buffer to a DXF string.
|
|
376
|
+
* The returned string must be valid DXF parseable by `parseDxf()`.
|
|
377
|
+
*/
|
|
378
|
+
convert(buffer: ArrayBuffer): Promise<string>;
|
|
379
|
+
}
|
|
362
380
|
interface CadViewerOptions {
|
|
363
381
|
theme?: Theme;
|
|
364
382
|
backgroundColor?: string;
|
|
@@ -367,6 +385,8 @@ interface CadViewerOptions {
|
|
|
367
385
|
maxZoom?: number;
|
|
368
386
|
zoomSpeed?: number;
|
|
369
387
|
initialTool?: Tool;
|
|
388
|
+
/** Format converters for non-DXF file formats (e.g. DWG via @cadview/dwg). */
|
|
389
|
+
formatConverters?: FormatConverter[];
|
|
370
390
|
}
|
|
371
391
|
declare class CadViewer {
|
|
372
392
|
private canvas;
|
|
@@ -381,14 +401,50 @@ declare class CadViewer {
|
|
|
381
401
|
private currentTool;
|
|
382
402
|
private inputHandler;
|
|
383
403
|
private resizeObserver;
|
|
404
|
+
private formatConverters;
|
|
384
405
|
private selectedEntityIndex;
|
|
385
406
|
private renderPending;
|
|
386
407
|
private destroyed;
|
|
408
|
+
private loadGeneration;
|
|
387
409
|
private mouseScreenX;
|
|
388
410
|
private mouseScreenY;
|
|
389
411
|
constructor(canvas: HTMLCanvasElement, options?: CadViewerOptions);
|
|
412
|
+
/**
|
|
413
|
+
* Throws if the viewer has been destroyed.
|
|
414
|
+
* Call at the start of any public method that mutates state.
|
|
415
|
+
*/
|
|
416
|
+
private guardDestroyed;
|
|
417
|
+
/**
|
|
418
|
+
* Run registered format converters on a buffer.
|
|
419
|
+
* Returns the converted DXF string if a converter matched, or null otherwise.
|
|
420
|
+
* Each converter's detect() is wrapped in try/catch — a throwing detect() is skipped.
|
|
421
|
+
*/
|
|
422
|
+
private runConverters;
|
|
423
|
+
/**
|
|
424
|
+
* Load a CAD file from a browser File object.
|
|
425
|
+
* Automatically detects the format using registered converters (e.g. DWG).
|
|
426
|
+
* Falls back to DXF parsing if no converter matches.
|
|
427
|
+
*/
|
|
390
428
|
loadFile(file: File): Promise<void>;
|
|
429
|
+
/**
|
|
430
|
+
* Load a CAD file from an ArrayBuffer with format converter support.
|
|
431
|
+
* Unlike `loadArrayBuffer()` (sync, DXF-only), this method is async and
|
|
432
|
+
* checks registered FormatConverters for non-DXF formats.
|
|
433
|
+
*/
|
|
434
|
+
loadBuffer(buffer: ArrayBuffer): Promise<void>;
|
|
435
|
+
/**
|
|
436
|
+
* Load a pre-parsed DxfDocument directly, bypassing the parser.
|
|
437
|
+
* Useful for custom parsers or pre-processed documents.
|
|
438
|
+
*/
|
|
439
|
+
loadDocument(doc: DxfDocument): void;
|
|
440
|
+
/**
|
|
441
|
+
* Load a DXF string directly (synchronous, no format conversion).
|
|
442
|
+
*/
|
|
391
443
|
loadString(dxf: string): void;
|
|
444
|
+
/**
|
|
445
|
+
* Load a DXF file from an ArrayBuffer (synchronous, no format conversion).
|
|
446
|
+
* For format conversion support (e.g. DWG), use `loadFile()` or `loadBuffer()` instead.
|
|
447
|
+
*/
|
|
392
448
|
loadArrayBuffer(buffer: ArrayBuffer): void;
|
|
393
449
|
/**
|
|
394
450
|
* Clear the current document and reset all state without destroying the viewer.
|
|
@@ -507,4 +563,4 @@ interface BBox {
|
|
|
507
563
|
declare function computeEntitiesBounds(entities: DxfEntity[]): BBox | null;
|
|
508
564
|
declare function computeEntityBBox(entity: DxfEntity): BBox | null;
|
|
509
565
|
|
|
510
|
-
export { type BBox, CadViewer, type CadViewerEventMap, type CadViewerOptions, Camera, CanvasRenderer, type DxfArcEntity, type DxfAttrib, type DxfBlock, type DxfCircleEntity, type DxfDimensionEntity, type DxfDocument, type DxfEllipseEntity, type DxfEntity, type DxfEntityBase, type DxfHatchBoundaryPath, type DxfHatchEdge, type DxfHatchEntity, type DxfHeader, type DxfInsertEntity, type DxfLayer, type DxfLineEntity, type DxfLineType, type DxfLwPolylineEntity, type DxfLwPolylineVertex, type DxfMTextEntity, DxfParseError, type DxfPointEntity, type DxfPolylineEntity, type DxfSplineEntity, type DxfStyle, type DxfTextEntity, EventEmitter, LayerManager, type MeasureEvent, type MeasureState, MeasureTool, type Point2D, type Point3D, type SelectEvent, type SnapResult, type SnapType, SpatialIndex, THEMES, type Theme, type ThemeConfig, type Tool, type ViewTransform, aciToDisplayColor, aciToHex, applyTransform, computeEntitiesBounds, computeEntityBBox, drawEntity, findSnaps, fitToView, hitTest, parseDxf, renderMeasureOverlay, resolveEntityColor, screenToWorld, trueColorToHex, worldToScreen, zoomAtPoint };
|
|
566
|
+
export { type BBox, CadViewer, type CadViewerEventMap, type CadViewerOptions, Camera, CanvasRenderer, type DxfArcEntity, type DxfAttrib, type DxfBlock, type DxfCircleEntity, type DxfDimensionEntity, type DxfDocument, type DxfEllipseEntity, type DxfEntity, type DxfEntityBase, type DxfHatchBoundaryPath, type DxfHatchEdge, type DxfHatchEntity, type DxfHeader, type DxfInsertEntity, type DxfLayer, type DxfLineEntity, type DxfLineType, type DxfLwPolylineEntity, type DxfLwPolylineVertex, type DxfMTextEntity, DxfParseError, type DxfPointEntity, type DxfPolylineEntity, type DxfSplineEntity, type DxfStyle, type DxfTextEntity, EventEmitter, type FormatConverter, LayerManager, type MeasureEvent, type MeasureState, MeasureTool, type Point2D, type Point3D, type SelectEvent, type SnapResult, type SnapType, SpatialIndex, THEMES, type Theme, type ThemeConfig, type Tool, type ViewTransform, aciToDisplayColor, aciToHex, applyTransform, computeEntitiesBounds, computeEntityBBox, drawEntity, findSnaps, fitToView, hitTest, parseDxf, renderMeasureOverlay, resolveEntityColor, screenToWorld, trueColorToHex, worldToScreen, zoomAtPoint };
|
package/dist/index.js
CHANGED
|
@@ -1545,7 +1545,7 @@ function decodeInput(input) {
|
|
|
1545
1545
|
const bytes = new Uint8Array(input);
|
|
1546
1546
|
const sentinelBytes = new TextDecoder("ascii").decode(bytes.slice(0, BINARY_DXF_SENTINEL.length));
|
|
1547
1547
|
if (sentinelBytes === BINARY_DXF_SENTINEL) {
|
|
1548
|
-
throw new
|
|
1548
|
+
throw new DxfParseError("Binary DXF format is not supported. Please export as ASCII DXF.");
|
|
1549
1549
|
}
|
|
1550
1550
|
let text = new TextDecoder("utf-8").decode(input);
|
|
1551
1551
|
const versionMatch = text.match(/\$ACADVER[\s\S]*?\n\s*1\s*\n\s*(\S+)/);
|
|
@@ -1616,7 +1616,7 @@ function parseDxf(input) {
|
|
|
1616
1616
|
try {
|
|
1617
1617
|
text = decodeInput(input);
|
|
1618
1618
|
} catch (err) {
|
|
1619
|
-
if (err instanceof
|
|
1619
|
+
if (err instanceof DxfParseError) {
|
|
1620
1620
|
throw err;
|
|
1621
1621
|
}
|
|
1622
1622
|
throw new DxfParseError("Failed to decode DXF input.", err);
|
|
@@ -2479,23 +2479,25 @@ function deBoor(degree, controlPoints, knots, t, weights) {
|
|
|
2479
2479
|
const denom = knots[i + degree - r + 1] - knots[i];
|
|
2480
2480
|
if (Math.abs(denom) < 1e-10) continue;
|
|
2481
2481
|
const alpha = (t - knots[i]) / denom;
|
|
2482
|
+
const dj = d[j];
|
|
2483
|
+
const djPrev = d[j - 1];
|
|
2482
2484
|
if (weights) {
|
|
2483
2485
|
const w0 = w[j - 1] * (1 - alpha);
|
|
2484
2486
|
const w1 = w[j] * alpha;
|
|
2485
2487
|
const wSum = w0 + w1;
|
|
2486
2488
|
if (Math.abs(wSum) < 1e-10) continue;
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2489
|
+
dj.x = (djPrev.x * w0 + dj.x * w1) / wSum;
|
|
2490
|
+
dj.y = (djPrev.y * w0 + dj.y * w1) / wSum;
|
|
2491
|
+
dj.z = (djPrev.z * w0 + dj.z * w1) / wSum;
|
|
2490
2492
|
w[j] = wSum;
|
|
2491
2493
|
} else {
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2494
|
+
dj.x = (1 - alpha) * djPrev.x + alpha * dj.x;
|
|
2495
|
+
dj.y = (1 - alpha) * djPrev.y + alpha * dj.y;
|
|
2496
|
+
dj.z = (1 - alpha) * djPrev.z + alpha * dj.z;
|
|
2495
2497
|
}
|
|
2496
2498
|
}
|
|
2497
2499
|
}
|
|
2498
|
-
return d[degree];
|
|
2500
|
+
return d[degree] ?? { x: 0, y: 0, z: 0 };
|
|
2499
2501
|
}
|
|
2500
2502
|
function fitPointsToPolyline(fitPoints) {
|
|
2501
2503
|
if (fitPoints.length < 2) return fitPoints.map((p) => ({ x: p.x, y: p.y }));
|
|
@@ -3711,9 +3713,11 @@ var CadViewer = class {
|
|
|
3711
3713
|
currentTool;
|
|
3712
3714
|
inputHandler;
|
|
3713
3715
|
resizeObserver;
|
|
3716
|
+
formatConverters;
|
|
3714
3717
|
selectedEntityIndex = -1;
|
|
3715
3718
|
renderPending = false;
|
|
3716
3719
|
destroyed = false;
|
|
3720
|
+
loadGeneration = 0;
|
|
3717
3721
|
mouseScreenX = 0;
|
|
3718
3722
|
mouseScreenY = 0;
|
|
3719
3723
|
constructor(canvas, options) {
|
|
@@ -3727,6 +3731,7 @@ var CadViewer = class {
|
|
|
3727
3731
|
zoomSpeed: options?.zoomSpeed ?? 1.1,
|
|
3728
3732
|
initialTool: options?.initialTool ?? "pan"
|
|
3729
3733
|
};
|
|
3734
|
+
this.formatConverters = options?.formatConverters ?? [];
|
|
3730
3735
|
this.renderer = new CanvasRenderer(canvas);
|
|
3731
3736
|
this.camera = new Camera(this.options);
|
|
3732
3737
|
this.layerManager = new LayerManager();
|
|
@@ -3741,15 +3746,91 @@ var CadViewer = class {
|
|
|
3741
3746
|
this.requestRender();
|
|
3742
3747
|
}
|
|
3743
3748
|
// === Loading ===
|
|
3749
|
+
/**
|
|
3750
|
+
* Throws if the viewer has been destroyed.
|
|
3751
|
+
* Call at the start of any public method that mutates state.
|
|
3752
|
+
*/
|
|
3753
|
+
guardDestroyed() {
|
|
3754
|
+
if (this.destroyed) {
|
|
3755
|
+
throw new Error("CadViewer: cannot call methods on a destroyed instance.");
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
/**
|
|
3759
|
+
* Run registered format converters on a buffer.
|
|
3760
|
+
* Returns the converted DXF string if a converter matched, or null otherwise.
|
|
3761
|
+
* Each converter's detect() is wrapped in try/catch — a throwing detect() is skipped.
|
|
3762
|
+
*/
|
|
3763
|
+
async runConverters(buffer) {
|
|
3764
|
+
for (const converter of this.formatConverters) {
|
|
3765
|
+
let detected = false;
|
|
3766
|
+
try {
|
|
3767
|
+
detected = converter.detect(buffer);
|
|
3768
|
+
} catch {
|
|
3769
|
+
continue;
|
|
3770
|
+
}
|
|
3771
|
+
if (detected) {
|
|
3772
|
+
return converter.convert(buffer);
|
|
3773
|
+
}
|
|
3774
|
+
}
|
|
3775
|
+
return null;
|
|
3776
|
+
}
|
|
3777
|
+
/**
|
|
3778
|
+
* Load a CAD file from a browser File object.
|
|
3779
|
+
* Automatically detects the format using registered converters (e.g. DWG).
|
|
3780
|
+
* Falls back to DXF parsing if no converter matches.
|
|
3781
|
+
*/
|
|
3744
3782
|
async loadFile(file) {
|
|
3783
|
+
this.guardDestroyed();
|
|
3784
|
+
const generation = ++this.loadGeneration;
|
|
3745
3785
|
const buffer = await file.arrayBuffer();
|
|
3746
|
-
this.
|
|
3786
|
+
if (this.destroyed || generation !== this.loadGeneration) return;
|
|
3787
|
+
const dxfString = await this.runConverters(buffer);
|
|
3788
|
+
if (this.destroyed || generation !== this.loadGeneration) return;
|
|
3789
|
+
this.doc = dxfString != null ? parseDxf(dxfString) : parseDxf(buffer);
|
|
3790
|
+
this.onDocumentLoaded();
|
|
3747
3791
|
}
|
|
3792
|
+
/**
|
|
3793
|
+
* Load a CAD file from an ArrayBuffer with format converter support.
|
|
3794
|
+
* Unlike `loadArrayBuffer()` (sync, DXF-only), this method is async and
|
|
3795
|
+
* checks registered FormatConverters for non-DXF formats.
|
|
3796
|
+
*/
|
|
3797
|
+
async loadBuffer(buffer) {
|
|
3798
|
+
this.guardDestroyed();
|
|
3799
|
+
const generation = ++this.loadGeneration;
|
|
3800
|
+
const dxfString = await this.runConverters(buffer);
|
|
3801
|
+
if (this.destroyed || generation !== this.loadGeneration) return;
|
|
3802
|
+
this.doc = dxfString != null ? parseDxf(dxfString) : parseDxf(buffer);
|
|
3803
|
+
this.onDocumentLoaded();
|
|
3804
|
+
}
|
|
3805
|
+
/**
|
|
3806
|
+
* Load a pre-parsed DxfDocument directly, bypassing the parser.
|
|
3807
|
+
* Useful for custom parsers or pre-processed documents.
|
|
3808
|
+
*/
|
|
3809
|
+
loadDocument(doc) {
|
|
3810
|
+
this.guardDestroyed();
|
|
3811
|
+
++this.loadGeneration;
|
|
3812
|
+
if (!doc || !Array.isArray(doc.entities) || !(doc.layers instanceof Map)) {
|
|
3813
|
+
throw new Error("CadViewer: invalid DxfDocument \u2014 expected entities array and layers Map.");
|
|
3814
|
+
}
|
|
3815
|
+
this.doc = doc;
|
|
3816
|
+
this.onDocumentLoaded();
|
|
3817
|
+
}
|
|
3818
|
+
/**
|
|
3819
|
+
* Load a DXF string directly (synchronous, no format conversion).
|
|
3820
|
+
*/
|
|
3748
3821
|
loadString(dxf) {
|
|
3822
|
+
this.guardDestroyed();
|
|
3823
|
+
++this.loadGeneration;
|
|
3749
3824
|
this.doc = parseDxf(dxf);
|
|
3750
3825
|
this.onDocumentLoaded();
|
|
3751
3826
|
}
|
|
3827
|
+
/**
|
|
3828
|
+
* Load a DXF file from an ArrayBuffer (synchronous, no format conversion).
|
|
3829
|
+
* For format conversion support (e.g. DWG), use `loadFile()` or `loadBuffer()` instead.
|
|
3830
|
+
*/
|
|
3752
3831
|
loadArrayBuffer(buffer) {
|
|
3832
|
+
this.guardDestroyed();
|
|
3833
|
+
++this.loadGeneration;
|
|
3753
3834
|
this.doc = parseDxf(buffer);
|
|
3754
3835
|
this.onDocumentLoaded();
|
|
3755
3836
|
}
|
|
@@ -3757,6 +3838,8 @@ var CadViewer = class {
|
|
|
3757
3838
|
* Clear the current document and reset all state without destroying the viewer.
|
|
3758
3839
|
*/
|
|
3759
3840
|
clearDocument() {
|
|
3841
|
+
this.guardDestroyed();
|
|
3842
|
+
++this.loadGeneration;
|
|
3760
3843
|
this.doc = null;
|
|
3761
3844
|
this.selectedEntityIndex = -1;
|
|
3762
3845
|
this.spatialIndex.clear();
|
|
@@ -3777,6 +3860,7 @@ var CadViewer = class {
|
|
|
3777
3860
|
}
|
|
3778
3861
|
// === Camera Controls ===
|
|
3779
3862
|
fitToView() {
|
|
3863
|
+
this.guardDestroyed();
|
|
3780
3864
|
if (!this.doc) return;
|
|
3781
3865
|
const bounds = this.computeDocumentBounds();
|
|
3782
3866
|
if (!bounds) return;
|
|
@@ -3788,6 +3872,7 @@ var CadViewer = class {
|
|
|
3788
3872
|
this.emitter.emit("viewchange", this.camera.getTransform());
|
|
3789
3873
|
}
|
|
3790
3874
|
zoomTo(scale) {
|
|
3875
|
+
this.guardDestroyed();
|
|
3791
3876
|
const rect = this.canvas.getBoundingClientRect();
|
|
3792
3877
|
const centerX = rect.width / 2;
|
|
3793
3878
|
const centerY = rect.height / 2;
|
|
@@ -3797,6 +3882,7 @@ var CadViewer = class {
|
|
|
3797
3882
|
this.emitter.emit("viewchange", this.camera.getTransform());
|
|
3798
3883
|
}
|
|
3799
3884
|
panTo(worldX, worldY) {
|
|
3885
|
+
this.guardDestroyed();
|
|
3800
3886
|
const rect = this.canvas.getBoundingClientRect();
|
|
3801
3887
|
const vt = this.camera.getTransform();
|
|
3802
3888
|
const currentSX = worldX * vt.scale + vt.offsetX;
|
|
@@ -3819,15 +3905,18 @@ var CadViewer = class {
|
|
|
3819
3905
|
return this.layerManager.getAllLayers();
|
|
3820
3906
|
}
|
|
3821
3907
|
setLayerVisible(name, visible) {
|
|
3908
|
+
this.guardDestroyed();
|
|
3822
3909
|
this.layerManager.setVisible(name, visible);
|
|
3823
3910
|
this.requestRender();
|
|
3824
3911
|
}
|
|
3825
3912
|
setLayerColor(name, color) {
|
|
3913
|
+
this.guardDestroyed();
|
|
3826
3914
|
this.layerManager.setColorOverride(name, color);
|
|
3827
3915
|
this.requestRender();
|
|
3828
3916
|
}
|
|
3829
3917
|
// === Theme ===
|
|
3830
3918
|
setTheme(theme) {
|
|
3919
|
+
this.guardDestroyed();
|
|
3831
3920
|
this.options.theme = theme;
|
|
3832
3921
|
this.requestRender();
|
|
3833
3922
|
}
|
|
@@ -3835,11 +3924,13 @@ var CadViewer = class {
|
|
|
3835
3924
|
return this.options.theme;
|
|
3836
3925
|
}
|
|
3837
3926
|
setBackgroundColor(color) {
|
|
3927
|
+
this.guardDestroyed();
|
|
3838
3928
|
this.options.backgroundColor = color;
|
|
3839
3929
|
this.requestRender();
|
|
3840
3930
|
}
|
|
3841
3931
|
// === Tools ===
|
|
3842
3932
|
setTool(tool) {
|
|
3933
|
+
this.guardDestroyed();
|
|
3843
3934
|
if (this.currentTool === "measure" && tool !== "measure") {
|
|
3844
3935
|
this.measureTool.deactivate();
|
|
3845
3936
|
}
|