@mlightcad/cad-pdf-plugin 1.8.0-preview.2 → 1.8.0-preview.4
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/LICENSE +21 -21
- package/README.md +280 -186
- package/dist/cad-pdf-plugin-register.js +29 -11
- package/dist/cad-pdf-plugin-register.umd.cjs +1 -1
- package/dist/cad-pdf-plugin.js +17568 -8428
- package/dist/cad-pdf-plugin.umd.cjs +847 -13
- package/lib/AcApConvertToPdfCmd.d.ts.map +1 -1
- package/lib/AcApConvertToPdfCmd.js +14 -3
- package/lib/AcApConvertToPdfCmd.js.map +1 -1
- package/lib/AcApImportPdfCmd.d.ts +5 -3
- package/lib/AcApImportPdfCmd.d.ts.map +1 -1
- package/lib/AcApImportPdfCmd.js +5 -3
- package/lib/AcApImportPdfCmd.js.map +1 -1
- package/lib/AcApImportPdfPromptCmd.d.ts +16 -0
- package/lib/AcApImportPdfPromptCmd.d.ts.map +1 -0
- package/lib/AcApImportPdfPromptCmd.js +89 -0
- package/lib/AcApImportPdfPromptCmd.js.map +1 -0
- package/lib/AcApPdfBlockCmd.d.ts +15 -0
- package/lib/AcApPdfBlockCmd.d.ts.map +1 -0
- package/lib/AcApPdfBlockCmd.js +75 -0
- package/lib/AcApPdfBlockCmd.js.map +1 -0
- package/lib/AcApPdfDimCmd.d.ts +20 -0
- package/lib/AcApPdfDimCmd.d.ts.map +1 -0
- package/lib/AcApPdfDimCmd.js +413 -0
- package/lib/AcApPdfDimCmd.js.map +1 -0
- package/lib/AcApPdfDimSession.d.ts +82 -0
- package/lib/AcApPdfDimSession.d.ts.map +1 -0
- package/lib/AcApPdfDimSession.js +252 -0
- package/lib/AcApPdfDimSession.js.map +1 -0
- package/lib/AcApPdfFontResolver.d.ts.map +1 -1
- package/lib/AcApPdfFontResolver.js +2 -5
- package/lib/AcApPdfFontResolver.js.map +1 -1
- package/lib/AcApPdfHatchCmd.d.ts +33 -0
- package/lib/AcApPdfHatchCmd.d.ts.map +1 -0
- package/lib/AcApPdfHatchCmd.js +411 -0
- package/lib/AcApPdfHatchCmd.js.map +1 -0
- package/lib/AcApPdfHatchSession.d.ts +122 -0
- package/lib/AcApPdfHatchSession.d.ts.map +1 -0
- package/lib/AcApPdfHatchSession.js +357 -0
- package/lib/AcApPdfHatchSession.js.map +1 -0
- package/lib/AcApPdfImportConvertor.d.ts +47 -5
- package/lib/AcApPdfImportConvertor.d.ts.map +1 -1
- package/lib/AcApPdfImportConvertor.js +999 -108
- package/lib/AcApPdfImportConvertor.js.map +1 -1
- package/lib/AcApPdfImportOptions.d.ts +116 -0
- package/lib/AcApPdfImportOptions.d.ts.map +1 -0
- package/lib/AcApPdfImportOptions.js +31 -0
- package/lib/AcApPdfImportOptions.js.map +1 -0
- package/lib/AcApPdfImportResources.d.ts +41 -0
- package/lib/AcApPdfImportResources.d.ts.map +1 -0
- package/lib/AcApPdfImportResources.js +52 -0
- package/lib/AcApPdfImportResources.js.map +1 -0
- package/lib/AcApPdfPlugin.d.ts +3 -3
- package/lib/AcApPdfPlugin.d.ts.map +1 -1
- package/lib/AcApPdfPlugin.js +23 -5
- package/lib/AcApPdfPlugin.js.map +1 -1
- package/lib/AcApPdfScaleCmd.d.ts +22 -0
- package/lib/AcApPdfScaleCmd.d.ts.map +1 -0
- package/lib/AcApPdfScaleCmd.js +185 -0
- package/lib/AcApPdfScaleCmd.js.map +1 -0
- package/lib/AcApPdfTextCmd.d.ts +73 -0
- package/lib/AcApPdfTextCmd.d.ts.map +1 -0
- package/lib/AcApPdfTextCmd.js +777 -0
- package/lib/AcApPdfTextCmd.js.map +1 -0
- package/lib/AcApPdfTextSession.d.ts +232 -0
- package/lib/AcApPdfTextSession.d.ts.map +1 -0
- package/lib/AcApPdfTextSession.js +826 -0
- package/lib/AcApPdfTextSession.js.map +1 -0
- package/lib/acapPdfI18n.d.ts +11 -0
- package/lib/acapPdfI18n.d.ts.map +1 -0
- package/lib/acapPdfI18n.js +57 -0
- package/lib/acapPdfI18n.js.map +1 -0
- package/lib/acapPdfPrompts.d.ts +12 -0
- package/lib/acapPdfPrompts.d.ts.map +1 -0
- package/lib/acapPdfPrompts.js +100 -0
- package/lib/acapPdfPrompts.js.map +1 -0
- package/lib/index.d.ts +28 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +28 -0
- package/lib/index.js.map +1 -1
- package/lib/pdfDeprecatedMatching.d.ts +27 -0
- package/lib/pdfDeprecatedMatching.d.ts.map +1 -0
- package/lib/pdfDeprecatedMatching.js +20 -0
- package/lib/pdfDeprecatedMatching.js.map +1 -0
- package/lib/pdfDimStrokeTexts.d.ts +55 -0
- package/lib/pdfDimStrokeTexts.d.ts.map +1 -0
- package/lib/pdfDimStrokeTexts.js +274 -0
- package/lib/pdfDimStrokeTexts.js.map +1 -0
- package/lib/pdfDimensionConvert.d.ts +80 -0
- package/lib/pdfDimensionConvert.d.ts.map +1 -0
- package/lib/pdfDimensionConvert.js +566 -0
- package/lib/pdfDimensionConvert.js.map +1 -0
- package/lib/pdfEntityStrokes.d.ts +13 -0
- package/lib/pdfEntityStrokes.d.ts.map +1 -0
- package/lib/pdfEntityStrokes.js +86 -0
- package/lib/pdfEntityStrokes.js.map +1 -0
- package/lib/pdfHatchRecover.d.ts +57 -0
- package/lib/pdfHatchRecover.d.ts.map +1 -0
- package/lib/pdfHatchRecover.js +315 -0
- package/lib/pdfHatchRecover.js.map +1 -0
- package/lib/pdfImportAppend.d.ts +24 -0
- package/lib/pdfImportAppend.d.ts.map +1 -0
- package/lib/pdfImportAppend.js +35 -0
- package/lib/pdfImportAppend.js.map +1 -0
- package/lib/pdfImportEntities.d.ts +63 -0
- package/lib/pdfImportEntities.d.ts.map +1 -0
- package/lib/pdfImportEntities.js +307 -0
- package/lib/pdfImportEntities.js.map +1 -0
- package/lib/pdfImportImages.d.ts +90 -0
- package/lib/pdfImportImages.d.ts.map +1 -0
- package/lib/pdfImportImages.js +294 -0
- package/lib/pdfImportImages.js.map +1 -0
- package/lib/pdfImportShapes.d.ts +63 -0
- package/lib/pdfImportShapes.d.ts.map +1 -0
- package/lib/pdfImportShapes.js +248 -0
- package/lib/pdfImportShapes.js.map +1 -0
- package/lib/pdfVectorImport.d.ts +218 -5
- package/lib/pdfVectorImport.d.ts.map +1 -1
- package/lib/pdfVectorImport.js +566 -98
- package/lib/pdfVectorImport.js.map +1 -1
- package/lib/recognition/pdfCurveRecognition.d.ts +91 -0
- package/lib/recognition/pdfCurveRecognition.d.ts.map +1 -0
- package/lib/recognition/pdfCurveRecognition.js +506 -0
- package/lib/recognition/pdfCurveRecognition.js.map +1 -0
- package/lib/recognition/pdfDimDigitRecognition.d.ts +18 -0
- package/lib/recognition/pdfDimDigitRecognition.d.ts.map +1 -0
- package/lib/recognition/pdfDimDigitRecognition.js +520 -0
- package/lib/recognition/pdfDimDigitRecognition.js.map +1 -0
- package/lib/recognition/pdfDimensionPattern.d.ts +173 -0
- package/lib/recognition/pdfDimensionPattern.d.ts.map +1 -0
- package/lib/recognition/pdfDimensionPattern.js +1023 -0
- package/lib/recognition/pdfDimensionPattern.js.map +1 -0
- package/lib/recognition/pdfFormBlocks.d.ts +58 -0
- package/lib/recognition/pdfFormBlocks.d.ts.map +1 -0
- package/lib/recognition/pdfFormBlocks.js +260 -0
- package/lib/recognition/pdfFormBlocks.js.map +1 -0
- package/lib/recognition/pdfGlyphClustering.d.ts +81 -0
- package/lib/recognition/pdfGlyphClustering.d.ts.map +1 -0
- package/lib/recognition/pdfGlyphClustering.js +1005 -0
- package/lib/recognition/pdfGlyphClustering.js.map +1 -0
- package/lib/recognition/pdfGlyphDictionary.d.ts +49 -0
- package/lib/recognition/pdfGlyphDictionary.d.ts.map +1 -0
- package/lib/recognition/pdfGlyphDictionary.js +188 -0
- package/lib/recognition/pdfGlyphDictionary.js.map +1 -0
- package/lib/recognition/pdfHatchFaces.d.ts +84 -0
- package/lib/recognition/pdfHatchFaces.d.ts.map +1 -0
- package/lib/recognition/pdfHatchFaces.js +1285 -0
- package/lib/recognition/pdfHatchFaces.js.map +1 -0
- package/lib/recognition/pdfHatchRecognition.d.ts +222 -0
- package/lib/recognition/pdfHatchRecognition.d.ts.map +1 -0
- package/lib/recognition/pdfHatchRecognition.js +3781 -0
- package/lib/recognition/pdfHatchRecognition.js.map +1 -0
- package/lib/recognition/pdfRecGeometry.d.ts +67 -0
- package/lib/recognition/pdfRecGeometry.d.ts.map +1 -0
- package/lib/recognition/pdfRecGeometry.js +365 -0
- package/lib/recognition/pdfRecGeometry.js.map +1 -0
- package/lib/recognition/pdfTextFontKind.d.ts +16 -0
- package/lib/recognition/pdfTextFontKind.d.ts.map +1 -0
- package/lib/recognition/pdfTextFontKind.js +51 -0
- package/lib/recognition/pdfTextFontKind.js.map +1 -0
- package/lib/recognition/pdfTextMerge.d.ts +71 -0
- package/lib/recognition/pdfTextMerge.d.ts.map +1 -0
- package/lib/recognition/pdfTextMerge.js +382 -0
- package/lib/recognition/pdfTextMerge.js.map +1 -0
- package/lib/recognition/pdfTextRunMerge.d.ts +28 -0
- package/lib/recognition/pdfTextRunMerge.d.ts.map +1 -0
- package/lib/recognition/pdfTextRunMerge.js +90 -0
- package/lib/recognition/pdfTextRunMerge.js.map +1 -0
- package/lib/register.d.ts +8 -2
- package/lib/register.d.ts.map +1 -1
- package/lib/register.js +29 -4
- package/lib/register.js.map +1 -1
- package/lib/ui/AcUiPdfDimPanel.d.ts +55 -0
- package/lib/ui/AcUiPdfDimPanel.d.ts.map +1 -0
- package/lib/ui/AcUiPdfDimPanel.js +347 -0
- package/lib/ui/AcUiPdfDimPanel.js.map +1 -0
- package/lib/ui/AcUiPdfHatchPanel.d.ts +57 -0
- package/lib/ui/AcUiPdfHatchPanel.d.ts.map +1 -0
- package/lib/ui/AcUiPdfHatchPanel.js +420 -0
- package/lib/ui/AcUiPdfHatchPanel.js.map +1 -0
- package/lib/ui/AcUiPdfImportDialog.d.ts +120 -0
- package/lib/ui/AcUiPdfImportDialog.d.ts.map +1 -0
- package/lib/ui/AcUiPdfImportDialog.js +673 -0
- package/lib/ui/AcUiPdfImportDialog.js.map +1 -0
- package/lib/ui/AcUiPdfTextPanel.d.ts +95 -0
- package/lib/ui/AcUiPdfTextPanel.d.ts.map +1 -0
- package/lib/ui/AcUiPdfTextPanel.js +775 -0
- package/lib/ui/AcUiPdfTextPanel.js.map +1 -0
- package/package.json +11 -11
|
@@ -0,0 +1,1285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hatch boundaries from the faces of the surrounding line work.
|
|
3
|
+
*
|
|
4
|
+
* A hatch written to PDF keeps its strokes but loses its boundary object;
|
|
5
|
+
* the boundary usually survives as ordinary lines, arcs and polylines that
|
|
6
|
+
* cross each other, meet in T-junctions and run on past the hatch. This
|
|
7
|
+
* module splits those edges at every intersection (a planar arrangement),
|
|
8
|
+
* walks the faces of the resulting graph and returns the outline of the
|
|
9
|
+
* faces that hold hatch strokes, holes included.
|
|
10
|
+
*
|
|
11
|
+
* Pure data in, pure data out.
|
|
12
|
+
*/
|
|
13
|
+
var __values = (this && this.__values) || function(o) {
|
|
14
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
15
|
+
if (m) return m.call(o);
|
|
16
|
+
if (o && typeof o.length === "number") return {
|
|
17
|
+
next: function () {
|
|
18
|
+
if (o && i >= o.length) o = void 0;
|
|
19
|
+
return { value: o && o[i++], done: !o };
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
23
|
+
};
|
|
24
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
25
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
26
|
+
if (!m) return o;
|
|
27
|
+
var i = m.call(o), r, ar = [], e;
|
|
28
|
+
try {
|
|
29
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
30
|
+
}
|
|
31
|
+
catch (error) { e = { error: error }; }
|
|
32
|
+
finally {
|
|
33
|
+
try {
|
|
34
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
35
|
+
}
|
|
36
|
+
finally { if (e) throw e.error; }
|
|
37
|
+
}
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
41
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
42
|
+
if (ar || !(i in from)) {
|
|
43
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
44
|
+
ar[i] = from[i];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
48
|
+
};
|
|
49
|
+
import { cubicAt } from './pdfRecGeometry';
|
|
50
|
+
/**
|
|
51
|
+
* Splits `edges` at every crossing and near touch and walks the faces of
|
|
52
|
+
* the result. Returns `undefined` when they enclose nothing or hold more
|
|
53
|
+
* than `maxSegments` segments.
|
|
54
|
+
*
|
|
55
|
+
* @param edges - Open or closed polylines of the line work.
|
|
56
|
+
*/
|
|
57
|
+
export function acapPdfFaceArrangement(edges, options) {
|
|
58
|
+
var _a;
|
|
59
|
+
var tol = options.tolerance;
|
|
60
|
+
var maxSegments = (_a = options.maxSegments) !== null && _a !== void 0 ? _a : 20000;
|
|
61
|
+
var segments = toSegments(edges, tol);
|
|
62
|
+
if (segments.length < 3 || segments.length > maxSegments)
|
|
63
|
+
return undefined;
|
|
64
|
+
var graph = buildGraph(segments, tol);
|
|
65
|
+
pruneDangling(graph);
|
|
66
|
+
if (graph.edges.length < 3)
|
|
67
|
+
return undefined;
|
|
68
|
+
var faces = traceFaces(graph);
|
|
69
|
+
var bounded = faces.filter(function (face) { return face.area > 0; });
|
|
70
|
+
if (bounded.length === 0)
|
|
71
|
+
return undefined;
|
|
72
|
+
var grid = new BoxGrid(bounded.map(function (face) { return face.box; }), bounded.length);
|
|
73
|
+
var arrangement = {
|
|
74
|
+
kind: 'pdfFaceArrangement',
|
|
75
|
+
graph: graph,
|
|
76
|
+
faces: faces,
|
|
77
|
+
bounded: bounded,
|
|
78
|
+
grid: grid,
|
|
79
|
+
tolerance: tol
|
|
80
|
+
};
|
|
81
|
+
return arrangement;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Outline loops (outer and holes, to be filled even-odd) of the faces of
|
|
85
|
+
* `edges` that contain the `hits`, or `undefined` when the edges do not
|
|
86
|
+
* enclose them.
|
|
87
|
+
*
|
|
88
|
+
* @param edges - Open or closed polylines of the line work around the hatch.
|
|
89
|
+
* @param hits - Points known to lie inside the hatch (stroke midpoints).
|
|
90
|
+
*/
|
|
91
|
+
export function acapPdfFaceBoundary(edges, hits, options) {
|
|
92
|
+
if (hits.length === 0)
|
|
93
|
+
return undefined;
|
|
94
|
+
var arrangement = acapPdfFaceArrangement(edges, options);
|
|
95
|
+
return arrangement
|
|
96
|
+
? acapPdfFaceBoundaryIn(arrangement, hits, options)
|
|
97
|
+
: undefined;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* {@link acapPdfFaceBoundary} on an arrangement built once with
|
|
101
|
+
* {@link acapPdfFaceArrangement}, for callers that try several hit sets
|
|
102
|
+
* against the same line work.
|
|
103
|
+
*
|
|
104
|
+
* @param arrangement - Faces of the line work around the hatch.
|
|
105
|
+
* @param hits - Points known to lie inside the hatch (stroke midpoints).
|
|
106
|
+
*/
|
|
107
|
+
export function acapPdfFaceBoundaryIn(arrangement, hits, options) {
|
|
108
|
+
var _a;
|
|
109
|
+
return (_a = acapPdfFaceBoundaryParts(arrangement, hits, options)) === null || _a === void 0 ? void 0 : _a[0];
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Like {@link acapPdfFaceBoundaryIn}, but split into separate hatches.
|
|
113
|
+
*
|
|
114
|
+
* Without `strokes` every face holding hits joins one outline. With them,
|
|
115
|
+
* two such faces join only when strokes run across the edge between them
|
|
116
|
+
* (a line drawn over one hatch, such as an axis). When strokes stop on the
|
|
117
|
+
* edge from both sides instead, each side was clipped to its own boundary:
|
|
118
|
+
* two hatches of one pattern that touch, kept apart.
|
|
119
|
+
*
|
|
120
|
+
* @param strokes - The hatch strokes the hits came from.
|
|
121
|
+
* @returns Outline loops per hatch, the one with the most hits first.
|
|
122
|
+
*/
|
|
123
|
+
export function acapPdfFaceBoundaryParts(arrangement, hits, options) {
|
|
124
|
+
var e_1, _a, e_2, _b, e_3, _c;
|
|
125
|
+
var _d, _e, _f, _g;
|
|
126
|
+
var minCoverage = (_d = options === null || options === void 0 ? void 0 : options.minCoverage) !== null && _d !== void 0 ? _d : 0.9;
|
|
127
|
+
if (hits.length === 0)
|
|
128
|
+
return undefined;
|
|
129
|
+
var state = arrangement;
|
|
130
|
+
var graph = state.graph, faces = state.faces, bounded = state.bounded, grid = state.grid;
|
|
131
|
+
// Each hit belongs to the smallest bounded face around it; a face of an
|
|
132
|
+
// island inside a bigger face is smaller, so islands come out right.
|
|
133
|
+
var hitCount = new Map();
|
|
134
|
+
var assigned = 0;
|
|
135
|
+
var _loop_1 = function (p) {
|
|
136
|
+
var best;
|
|
137
|
+
grid.forEachAt(p, function (i) {
|
|
138
|
+
var face = bounded[i];
|
|
139
|
+
if (best && face.area >= best.area)
|
|
140
|
+
return;
|
|
141
|
+
if (!inBox(p, face.box) || !pointInPolygon(p, face.points))
|
|
142
|
+
return;
|
|
143
|
+
best = face;
|
|
144
|
+
});
|
|
145
|
+
if (best) {
|
|
146
|
+
hitCount.set(best, ((_e = hitCount.get(best)) !== null && _e !== void 0 ? _e : 0) + 1);
|
|
147
|
+
assigned++;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
try {
|
|
151
|
+
for (var hits_1 = __values(hits), hits_1_1 = hits_1.next(); !hits_1_1.done; hits_1_1 = hits_1.next()) {
|
|
152
|
+
var p = hits_1_1.value;
|
|
153
|
+
_loop_1(p);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
157
|
+
finally {
|
|
158
|
+
try {
|
|
159
|
+
if (hits_1_1 && !hits_1_1.done && (_a = hits_1.return)) _a.call(hits_1);
|
|
160
|
+
}
|
|
161
|
+
finally { if (e_1) throw e_1.error; }
|
|
162
|
+
}
|
|
163
|
+
if (assigned < hits.length * minCoverage)
|
|
164
|
+
return undefined;
|
|
165
|
+
// Stray strokes (a dimension tick, a stub of another hatch) must not pull
|
|
166
|
+
// in a large empty face: keep faces whose hit density fits the rest.
|
|
167
|
+
var densities = __spreadArray([], __read(hitCount.entries()), false).map(function (_a) {
|
|
168
|
+
var _b = __read(_a, 2), face = _b[0], count = _b[1];
|
|
169
|
+
return count / face.area;
|
|
170
|
+
})
|
|
171
|
+
.sort(function (p, q) { return p - q; });
|
|
172
|
+
var median = densities[Math.floor(densities.length / 2)];
|
|
173
|
+
var selected = new Set();
|
|
174
|
+
var kept = 0;
|
|
175
|
+
try {
|
|
176
|
+
for (var hitCount_1 = __values(hitCount), hitCount_1_1 = hitCount_1.next(); !hitCount_1_1.done; hitCount_1_1 = hitCount_1.next()) {
|
|
177
|
+
var _h = __read(hitCount_1_1.value, 2), face = _h[0], count = _h[1];
|
|
178
|
+
// A face the hatch covers holds about as many hits as its area says;
|
|
179
|
+
// a big face with a few stray strokes does not. Small faces (expected
|
|
180
|
+
// to hold a handful) are judged leniently.
|
|
181
|
+
var expected = median * face.area;
|
|
182
|
+
var sparse = expected >= 6 ? count < expected * MIN_DENSITY_SHARE : count < 3;
|
|
183
|
+
if (sparse && count / face.area < median * 0.1)
|
|
184
|
+
continue;
|
|
185
|
+
if (sparse && expected >= 6)
|
|
186
|
+
continue;
|
|
187
|
+
selected.add(face);
|
|
188
|
+
kept += count;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
192
|
+
finally {
|
|
193
|
+
try {
|
|
194
|
+
if (hitCount_1_1 && !hitCount_1_1.done && (_b = hitCount_1.return)) _b.call(hitCount_1);
|
|
195
|
+
}
|
|
196
|
+
finally { if (e_2) throw e_2.error; }
|
|
197
|
+
}
|
|
198
|
+
if (kept < hits.length * minCoverage)
|
|
199
|
+
return undefined;
|
|
200
|
+
// Outer cycles of islands bound the face around them.
|
|
201
|
+
(_f = state.owner) !== null && _f !== void 0 ? _f : (state.owner = resolveHoleOwners(faces, bounded, grid));
|
|
202
|
+
var owner = state.owner;
|
|
203
|
+
var resolve = function (face) { var _a; return (_a = owner.get(face)) !== null && _a !== void 0 ? _a : face; };
|
|
204
|
+
var parts = splitFaces(graph, faces, resolve, selected, options === null || options === void 0 ? void 0 : options.strokes, state.tolerance);
|
|
205
|
+
var out = [];
|
|
206
|
+
var _loop_2 = function (part) {
|
|
207
|
+
var e_4, _j;
|
|
208
|
+
var loops = unionOutline(graph, faces, function (face) { return part.has(resolve(face)); }, state.tolerance);
|
|
209
|
+
if (!loops)
|
|
210
|
+
return "continue";
|
|
211
|
+
var count = 0;
|
|
212
|
+
try {
|
|
213
|
+
for (var part_1 = (e_4 = void 0, __values(part)), part_1_1 = part_1.next(); !part_1_1.done; part_1_1 = part_1.next()) {
|
|
214
|
+
var face = part_1_1.value;
|
|
215
|
+
count += (_g = hitCount.get(face)) !== null && _g !== void 0 ? _g : 0;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
219
|
+
finally {
|
|
220
|
+
try {
|
|
221
|
+
if (part_1_1 && !part_1_1.done && (_j = part_1.return)) _j.call(part_1);
|
|
222
|
+
}
|
|
223
|
+
finally { if (e_4) throw e_4.error; }
|
|
224
|
+
}
|
|
225
|
+
out.push({ loops: loops, hits: count });
|
|
226
|
+
};
|
|
227
|
+
try {
|
|
228
|
+
for (var parts_1 = __values(parts), parts_1_1 = parts_1.next(); !parts_1_1.done; parts_1_1 = parts_1.next()) {
|
|
229
|
+
var part = parts_1_1.value;
|
|
230
|
+
_loop_2(part);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
234
|
+
finally {
|
|
235
|
+
try {
|
|
236
|
+
if (parts_1_1 && !parts_1_1.done && (_c = parts_1.return)) _c.call(parts_1);
|
|
237
|
+
}
|
|
238
|
+
finally { if (e_3) throw e_3.error; }
|
|
239
|
+
}
|
|
240
|
+
if (out.length === 0)
|
|
241
|
+
return undefined;
|
|
242
|
+
return out.sort(function (p, q) { return q.hits - p.hits; }).map(function (part) { return part.loops; });
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Polyline through a recognized shape, with curves sampled so no chord is
|
|
246
|
+
* further than `chordTolerance` from the curve.
|
|
247
|
+
*/
|
|
248
|
+
export function acapPdfShapePolyline(shape, chordTolerance) {
|
|
249
|
+
var arcPoints = function (center, radius, start, sweep) {
|
|
250
|
+
var steps = arcSteps(radius, Math.abs(sweep), chordTolerance);
|
|
251
|
+
var out = [];
|
|
252
|
+
for (var i = 0; i <= steps; i++) {
|
|
253
|
+
var a = start + (sweep * i) / steps;
|
|
254
|
+
out.push({
|
|
255
|
+
x: center.x + radius * Math.cos(a),
|
|
256
|
+
y: center.y + radius * Math.sin(a)
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
return out;
|
|
260
|
+
};
|
|
261
|
+
switch (shape.kind) {
|
|
262
|
+
case 'line':
|
|
263
|
+
return [shape.start, shape.end];
|
|
264
|
+
case 'circle':
|
|
265
|
+
return arcPoints(shape.center, shape.radius, 0, Math.PI * 2);
|
|
266
|
+
case 'arc': {
|
|
267
|
+
var sweep = shape.endAngle - shape.startAngle;
|
|
268
|
+
if (sweep <= 0)
|
|
269
|
+
sweep += Math.PI * 2;
|
|
270
|
+
return arcPoints(shape.center, shape.radius, shape.startAngle, sweep);
|
|
271
|
+
}
|
|
272
|
+
case 'ellipse': {
|
|
273
|
+
var sweep = shape.endAngle - shape.startAngle;
|
|
274
|
+
if (sweep <= 0)
|
|
275
|
+
sweep += Math.PI * 2;
|
|
276
|
+
var major = Math.hypot(shape.majorAxis.x, shape.majorAxis.y);
|
|
277
|
+
var steps = arcSteps(major, sweep, chordTolerance);
|
|
278
|
+
var mx = shape.majorAxis.x;
|
|
279
|
+
var my = shape.majorAxis.y;
|
|
280
|
+
var out = [];
|
|
281
|
+
for (var i = 0; i <= steps; i++) {
|
|
282
|
+
var a = shape.startAngle + (sweep * i) / steps;
|
|
283
|
+
var cos = Math.cos(a);
|
|
284
|
+
var sin = Math.sin(a) * shape.radiusRatio;
|
|
285
|
+
out.push({
|
|
286
|
+
x: shape.center.x + mx * cos - my * sin,
|
|
287
|
+
y: shape.center.y + my * cos + mx * sin
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
return out;
|
|
291
|
+
}
|
|
292
|
+
case 'polyline': {
|
|
293
|
+
var v = shape.vertices;
|
|
294
|
+
var out = [];
|
|
295
|
+
var count = shape.closed ? v.length : v.length - 1;
|
|
296
|
+
for (var i = 0; i < count; i++) {
|
|
297
|
+
var a = v[i];
|
|
298
|
+
var b = v[(i + 1) % v.length];
|
|
299
|
+
if (Math.abs(a.bulge) <= 1e-12) {
|
|
300
|
+
out.push({ x: a.x, y: a.y });
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
var sweep = 4 * Math.atan(a.bulge);
|
|
304
|
+
var chord = Math.hypot(b.x - a.x, b.y - a.y);
|
|
305
|
+
var radius = chord / (2 * Math.sin(Math.abs(sweep) / 2));
|
|
306
|
+
var h = radius * Math.cos(Math.abs(sweep) / 2) * Math.sign(a.bulge);
|
|
307
|
+
var center = {
|
|
308
|
+
x: (a.x + b.x) / 2 - (h * (b.y - a.y)) / chord,
|
|
309
|
+
y: (a.y + b.y) / 2 + (h * (b.x - a.x)) / chord
|
|
310
|
+
};
|
|
311
|
+
var start = Math.atan2(a.y - center.y, a.x - center.x);
|
|
312
|
+
var arc = arcPoints(center, radius, start, sweep);
|
|
313
|
+
out.push.apply(out, __spreadArray([], __read(arc.slice(0, -1)), false));
|
|
314
|
+
}
|
|
315
|
+
var end = shape.closed ? v[0] : v[v.length - 1];
|
|
316
|
+
if (end)
|
|
317
|
+
out.push({ x: end.x, y: end.y });
|
|
318
|
+
return out;
|
|
319
|
+
}
|
|
320
|
+
case 'spline': {
|
|
321
|
+
var c = shape.controlPoints;
|
|
322
|
+
if (c.length < 4)
|
|
323
|
+
return c.map(function (p) { return ({ x: p.x, y: p.y }); });
|
|
324
|
+
var out = [c[0]];
|
|
325
|
+
for (var i = 0; i + 3 < c.length; i += 3) {
|
|
326
|
+
for (var k = 1; k <= 16; k++) {
|
|
327
|
+
out.push(cubicAt(c[i], c[i + 1], c[i + 2], c[i + 3], k / 16));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return out;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function arcSteps(radius, sweep, chordTolerance) {
|
|
335
|
+
// Sagitta r(1 - cos(θ/2)) <= tolerance.
|
|
336
|
+
var ratio = Math.min(1, Math.max(0, 1 - chordTolerance / radius));
|
|
337
|
+
var step = ratio > 0 ? 2 * Math.acos(ratio) : Math.PI / 4;
|
|
338
|
+
return Math.min(256, Math.max(2, Math.ceil(sweep / Math.max(step, 1e-3))));
|
|
339
|
+
}
|
|
340
|
+
function toSegments(edges, tol) {
|
|
341
|
+
var e_5, _a;
|
|
342
|
+
var out = [];
|
|
343
|
+
var min = tol * 0.01;
|
|
344
|
+
try {
|
|
345
|
+
for (var edges_1 = __values(edges), edges_1_1 = edges_1.next(); !edges_1_1.done; edges_1_1 = edges_1.next()) {
|
|
346
|
+
var polyline = edges_1_1.value;
|
|
347
|
+
for (var i = 0; i + 1 < polyline.length; i++) {
|
|
348
|
+
var a = polyline[i];
|
|
349
|
+
var b = polyline[i + 1];
|
|
350
|
+
if (Math.hypot(b.x - a.x, b.y - a.y) > min)
|
|
351
|
+
out.push([a, b]);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
356
|
+
finally {
|
|
357
|
+
try {
|
|
358
|
+
if (edges_1_1 && !edges_1_1.done && (_a = edges_1.return)) _a.call(edges_1);
|
|
359
|
+
}
|
|
360
|
+
finally { if (e_5) throw e_5.error; }
|
|
361
|
+
}
|
|
362
|
+
return out;
|
|
363
|
+
}
|
|
364
|
+
/** Splits segments at every crossing and near touch, snapping vertices. */
|
|
365
|
+
function buildGraph(segments, tol) {
|
|
366
|
+
var e_6, _a, e_7, _b;
|
|
367
|
+
var params = segments.map(function () { return [0, 1]; });
|
|
368
|
+
var boxes = segments.map(function (_a) {
|
|
369
|
+
var _b = __read(_a, 2), a = _b[0], b = _b[1];
|
|
370
|
+
return ({
|
|
371
|
+
minX: Math.min(a.x, b.x) - tol,
|
|
372
|
+
minY: Math.min(a.y, b.y) - tol,
|
|
373
|
+
maxX: Math.max(a.x, b.x) + tol,
|
|
374
|
+
maxY: Math.max(a.y, b.y) + tol
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
forEachNearPair(boxes, function (i, j) {
|
|
378
|
+
var _a = __read(segments[i], 2), a = _a[0], b = _a[1];
|
|
379
|
+
var _b = __read(segments[j], 2), c = _b[0], d = _b[1];
|
|
380
|
+
var cross = crossing(a, b, c, d);
|
|
381
|
+
if (cross) {
|
|
382
|
+
params[i].push(cross[0]);
|
|
383
|
+
params[j].push(cross[1]);
|
|
384
|
+
}
|
|
385
|
+
// T-junctions and ends that stop just short of (or past) another edge.
|
|
386
|
+
var t = projectWithin(a, c, d, tol);
|
|
387
|
+
if (t !== undefined)
|
|
388
|
+
params[j].push(t);
|
|
389
|
+
t = projectWithin(b, c, d, tol);
|
|
390
|
+
if (t !== undefined)
|
|
391
|
+
params[j].push(t);
|
|
392
|
+
t = projectWithin(c, a, b, tol);
|
|
393
|
+
if (t !== undefined)
|
|
394
|
+
params[i].push(t);
|
|
395
|
+
t = projectWithin(d, a, b, tol);
|
|
396
|
+
if (t !== undefined)
|
|
397
|
+
params[i].push(t);
|
|
398
|
+
});
|
|
399
|
+
// Snap grid with numeric cell keys (string keys dominate on big inputs).
|
|
400
|
+
var originX = Infinity;
|
|
401
|
+
var originY = Infinity;
|
|
402
|
+
var maxY = -Infinity;
|
|
403
|
+
try {
|
|
404
|
+
for (var boxes_1 = __values(boxes), boxes_1_1 = boxes_1.next(); !boxes_1_1.done; boxes_1_1 = boxes_1.next()) {
|
|
405
|
+
var box = boxes_1_1.value;
|
|
406
|
+
originX = Math.min(originX, box.minX);
|
|
407
|
+
originY = Math.min(originY, box.minY);
|
|
408
|
+
maxY = Math.max(maxY, box.maxY);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
412
|
+
finally {
|
|
413
|
+
try {
|
|
414
|
+
if (boxes_1_1 && !boxes_1_1.done && (_a = boxes_1.return)) _a.call(boxes_1);
|
|
415
|
+
}
|
|
416
|
+
finally { if (e_6) throw e_6.error; }
|
|
417
|
+
}
|
|
418
|
+
var cell = tol * 2;
|
|
419
|
+
// A spare cell on each side keeps neighbour keys from wrapping.
|
|
420
|
+
originX -= cell;
|
|
421
|
+
originY -= cell;
|
|
422
|
+
var stride = Math.floor((maxY - originY) / cell) + 3;
|
|
423
|
+
var points = [];
|
|
424
|
+
var grid = new Map();
|
|
425
|
+
var vertexAt = function (x, y) {
|
|
426
|
+
var e_8, _a;
|
|
427
|
+
var gx = Math.floor((x - originX) / cell);
|
|
428
|
+
var gy = Math.floor((y - originY) / cell);
|
|
429
|
+
for (var dx = -1; dx <= 1; dx++) {
|
|
430
|
+
for (var dy = -1; dy <= 1; dy++) {
|
|
431
|
+
var list_2 = grid.get((gx + dx) * stride + gy + dy);
|
|
432
|
+
if (!list_2)
|
|
433
|
+
continue;
|
|
434
|
+
try {
|
|
435
|
+
for (var list_1 = (e_8 = void 0, __values(list_2)), list_1_1 = list_1.next(); !list_1_1.done; list_1_1 = list_1.next()) {
|
|
436
|
+
var id_1 = list_1_1.value;
|
|
437
|
+
var q = points[id_1];
|
|
438
|
+
if (Math.hypot(q.x - x, q.y - y) <= tol)
|
|
439
|
+
return id_1;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
|
443
|
+
finally {
|
|
444
|
+
try {
|
|
445
|
+
if (list_1_1 && !list_1_1.done && (_a = list_1.return)) _a.call(list_1);
|
|
446
|
+
}
|
|
447
|
+
finally { if (e_8) throw e_8.error; }
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
var id = points.length;
|
|
452
|
+
points.push({ x: x, y: y });
|
|
453
|
+
var key = gx * stride + gy;
|
|
454
|
+
var list = grid.get(key);
|
|
455
|
+
if (list)
|
|
456
|
+
list.push(id);
|
|
457
|
+
else
|
|
458
|
+
grid.set(key, [id]);
|
|
459
|
+
return id;
|
|
460
|
+
};
|
|
461
|
+
var maxPoints = 0;
|
|
462
|
+
try {
|
|
463
|
+
for (var params_1 = __values(params), params_1_1 = params_1.next(); !params_1_1.done; params_1_1 = params_1.next()) {
|
|
464
|
+
var list = params_1_1.value;
|
|
465
|
+
maxPoints += list.length;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
|
469
|
+
finally {
|
|
470
|
+
try {
|
|
471
|
+
if (params_1_1 && !params_1_1.done && (_b = params_1.return)) _b.call(params_1);
|
|
472
|
+
}
|
|
473
|
+
finally { if (e_7) throw e_7.error; }
|
|
474
|
+
}
|
|
475
|
+
var seen = new Set();
|
|
476
|
+
var edges = [];
|
|
477
|
+
segments.forEach(function (_a, i) {
|
|
478
|
+
var e_9, _b;
|
|
479
|
+
var _c = __read(_a, 2), a = _c[0], b = _c[1];
|
|
480
|
+
var ts = params[i].sort(function (p, q) { return p - q; });
|
|
481
|
+
var prev = -1;
|
|
482
|
+
var last = NaN;
|
|
483
|
+
try {
|
|
484
|
+
for (var ts_1 = __values(ts), ts_1_1 = ts_1.next(); !ts_1_1.done; ts_1_1 = ts_1.next()) {
|
|
485
|
+
var t = ts_1_1.value;
|
|
486
|
+
if (t === last)
|
|
487
|
+
continue;
|
|
488
|
+
last = t;
|
|
489
|
+
var id = vertexAt(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t);
|
|
490
|
+
if (prev >= 0 && id !== prev) {
|
|
491
|
+
var key = prev < id ? prev * maxPoints + id : id * maxPoints + prev;
|
|
492
|
+
if (!seen.has(key)) {
|
|
493
|
+
seen.add(key);
|
|
494
|
+
edges.push([prev, id]);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
prev = id;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
catch (e_9_1) { e_9 = { error: e_9_1 }; }
|
|
501
|
+
finally {
|
|
502
|
+
try {
|
|
503
|
+
if (ts_1_1 && !ts_1_1.done && (_b = ts_1.return)) _b.call(ts_1);
|
|
504
|
+
}
|
|
505
|
+
finally { if (e_9) throw e_9.error; }
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
var out = points.map(function () { return []; });
|
|
509
|
+
edges.forEach(function (_a, e) {
|
|
510
|
+
var _b = __read(_a, 2), u = _b[0], v = _b[1];
|
|
511
|
+
out[u].push(2 * e);
|
|
512
|
+
out[v].push(2 * e + 1);
|
|
513
|
+
});
|
|
514
|
+
return { points: points, edges: edges, out: out };
|
|
515
|
+
}
|
|
516
|
+
/** Calls `fn` once for every pair of boxes that overlap. */
|
|
517
|
+
function forEachNearPair(boxes, fn) {
|
|
518
|
+
if (boxes.length < 2)
|
|
519
|
+
return;
|
|
520
|
+
var grid = new BoxGrid(boxes, boxes.length);
|
|
521
|
+
grid.forEachCell(function (ids, cx, cy) {
|
|
522
|
+
for (var p = 0; p < ids.length; p++) {
|
|
523
|
+
var a = boxes[ids[p]];
|
|
524
|
+
for (var q = p + 1; q < ids.length; q++) {
|
|
525
|
+
var b = boxes[ids[q]];
|
|
526
|
+
if (a.maxX < b.minX ||
|
|
527
|
+
b.maxX < a.minX ||
|
|
528
|
+
a.maxY < b.minY ||
|
|
529
|
+
b.maxY < a.minY) {
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
// Two boxes share several cells; only the one holding the low
|
|
533
|
+
// corner of their overlap reports the pair.
|
|
534
|
+
if (grid.cellX(Math.max(a.minX, b.minX)) !== cx ||
|
|
535
|
+
grid.cellY(Math.max(a.minY, b.minY)) !== cy) {
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
var i = ids[p];
|
|
539
|
+
var j = ids[q];
|
|
540
|
+
if (i < j)
|
|
541
|
+
fn(i, j);
|
|
542
|
+
else
|
|
543
|
+
fn(j, i);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Uniform grid over boxes in compressed rows with numeric cells. Cells
|
|
550
|
+
* follow the median box, enlarged so the grid stays near `cellBudget`
|
|
551
|
+
* cells.
|
|
552
|
+
*/
|
|
553
|
+
var BoxGrid = /** @class */ (function () {
|
|
554
|
+
function BoxGrid(boxes, cellBudget) {
|
|
555
|
+
var e_10, _a, e_11, _b;
|
|
556
|
+
var _this = this;
|
|
557
|
+
this.minX = 0;
|
|
558
|
+
this.minY = 0;
|
|
559
|
+
this.size = 1;
|
|
560
|
+
this.nx = 1;
|
|
561
|
+
this.ny = 1;
|
|
562
|
+
this.start = new Int32Array(2);
|
|
563
|
+
this.ids = new Int32Array(0);
|
|
564
|
+
var minX = Infinity;
|
|
565
|
+
var minY = Infinity;
|
|
566
|
+
var maxX = -Infinity;
|
|
567
|
+
var maxY = -Infinity;
|
|
568
|
+
try {
|
|
569
|
+
for (var boxes_2 = __values(boxes), boxes_2_1 = boxes_2.next(); !boxes_2_1.done; boxes_2_1 = boxes_2.next()) {
|
|
570
|
+
var b = boxes_2_1.value;
|
|
571
|
+
minX = Math.min(minX, b.minX);
|
|
572
|
+
minY = Math.min(minY, b.minY);
|
|
573
|
+
maxX = Math.max(maxX, b.maxX);
|
|
574
|
+
maxY = Math.max(maxY, b.maxY);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
catch (e_10_1) { e_10 = { error: e_10_1 }; }
|
|
578
|
+
finally {
|
|
579
|
+
try {
|
|
580
|
+
if (boxes_2_1 && !boxes_2_1.done && (_a = boxes_2.return)) _a.call(boxes_2);
|
|
581
|
+
}
|
|
582
|
+
finally { if (e_10) throw e_10.error; }
|
|
583
|
+
}
|
|
584
|
+
if (!Number.isFinite(minX + minY + maxX + maxY))
|
|
585
|
+
return;
|
|
586
|
+
var width = maxX - minX;
|
|
587
|
+
var height = maxY - minY;
|
|
588
|
+
// The median keeps short edges in few cells; the budget keeps a few
|
|
589
|
+
// long edges from multiplying the cell count.
|
|
590
|
+
var sizes = boxes.map(function (b) { return Math.max(b.maxX - b.minX, b.maxY - b.minY); });
|
|
591
|
+
sizes.sort(function (p, q) { return p - q; });
|
|
592
|
+
var typical = sizes[Math.floor(sizes.length / 2)];
|
|
593
|
+
var budget = Math.sqrt((width * height) / Math.max(1, cellBudget));
|
|
594
|
+
this.size = Math.max(typical, budget, width / 2048, height / 2048, 1e-9);
|
|
595
|
+
this.minX = minX;
|
|
596
|
+
this.minY = minY;
|
|
597
|
+
this.nx = Math.floor(width / this.size) + 1;
|
|
598
|
+
this.ny = Math.floor(height / this.size) + 1;
|
|
599
|
+
var counts = new Int32Array(this.nx * this.ny + 1);
|
|
600
|
+
try {
|
|
601
|
+
for (var boxes_3 = __values(boxes), boxes_3_1 = boxes_3.next(); !boxes_3_1.done; boxes_3_1 = boxes_3.next()) {
|
|
602
|
+
var b = boxes_3_1.value;
|
|
603
|
+
var x0 = this.cellX(b.minX);
|
|
604
|
+
var x1 = this.cellX(b.maxX);
|
|
605
|
+
var y0 = this.cellY(b.minY);
|
|
606
|
+
var y1 = this.cellY(b.maxY);
|
|
607
|
+
for (var x = x0; x <= x1; x++) {
|
|
608
|
+
for (var y = y0; y <= y1; y++)
|
|
609
|
+
counts[x * this.ny + y + 1]++;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
catch (e_11_1) { e_11 = { error: e_11_1 }; }
|
|
614
|
+
finally {
|
|
615
|
+
try {
|
|
616
|
+
if (boxes_3_1 && !boxes_3_1.done && (_b = boxes_3.return)) _b.call(boxes_3);
|
|
617
|
+
}
|
|
618
|
+
finally { if (e_11) throw e_11.error; }
|
|
619
|
+
}
|
|
620
|
+
for (var c = 1; c < counts.length; c++)
|
|
621
|
+
counts[c] += counts[c - 1];
|
|
622
|
+
this.start = counts.slice();
|
|
623
|
+
this.ids = new Int32Array(counts[counts.length - 1]);
|
|
624
|
+
boxes.forEach(function (b, i) {
|
|
625
|
+
var x0 = _this.cellX(b.minX);
|
|
626
|
+
var x1 = _this.cellX(b.maxX);
|
|
627
|
+
var y0 = _this.cellY(b.minY);
|
|
628
|
+
var y1 = _this.cellY(b.maxY);
|
|
629
|
+
for (var x = x0; x <= x1; x++) {
|
|
630
|
+
for (var y = y0; y <= y1; y++)
|
|
631
|
+
_this.ids[counts[x * _this.ny + y]++] = i;
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
BoxGrid.prototype.cellX = function (x) {
|
|
636
|
+
var c = Math.floor((x - this.minX) / this.size);
|
|
637
|
+
return c < 0 ? 0 : c >= this.nx ? this.nx - 1 : c;
|
|
638
|
+
};
|
|
639
|
+
BoxGrid.prototype.cellY = function (y) {
|
|
640
|
+
var c = Math.floor((y - this.minY) / this.size);
|
|
641
|
+
return c < 0 ? 0 : c >= this.ny ? this.ny - 1 : c;
|
|
642
|
+
};
|
|
643
|
+
/** Calls `fn` with every box id registered in the cell of `p`. */
|
|
644
|
+
BoxGrid.prototype.forEachAt = function (p, fn) {
|
|
645
|
+
var c = this.cellX(p.x) * this.ny + this.cellY(p.y);
|
|
646
|
+
for (var k = this.start[c]; k < this.start[c + 1]; k++)
|
|
647
|
+
fn(this.ids[k]);
|
|
648
|
+
};
|
|
649
|
+
/** Calls `fn` with the box ids of every cell that holds two or more. */
|
|
650
|
+
BoxGrid.prototype.forEachCell = function (fn) {
|
|
651
|
+
for (var x = 0; x < this.nx; x++) {
|
|
652
|
+
for (var y = 0; y < this.ny; y++) {
|
|
653
|
+
var c = x * this.ny + y;
|
|
654
|
+
var from = this.start[c];
|
|
655
|
+
var to = this.start[c + 1];
|
|
656
|
+
if (to - from >= 2)
|
|
657
|
+
fn(this.ids.subarray(from, to), x, y);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
return BoxGrid;
|
|
662
|
+
}());
|
|
663
|
+
/** Parameters where segments ab and cd cross, if they do. */
|
|
664
|
+
function crossing(a, b, c, d) {
|
|
665
|
+
var rx = b.x - a.x;
|
|
666
|
+
var ry = b.y - a.y;
|
|
667
|
+
var sx = d.x - c.x;
|
|
668
|
+
var sy = d.y - c.y;
|
|
669
|
+
var den = rx * sy - ry * sx;
|
|
670
|
+
if (Math.abs(den) <= 1e-12 * Math.hypot(rx, ry) * Math.hypot(sx, sy)) {
|
|
671
|
+
return undefined;
|
|
672
|
+
}
|
|
673
|
+
var qx = c.x - a.x;
|
|
674
|
+
var qy = c.y - a.y;
|
|
675
|
+
var t = (qx * sy - qy * sx) / den;
|
|
676
|
+
var u = (qx * ry - qy * rx) / den;
|
|
677
|
+
if (t < 0 || t > 1 || u < 0 || u > 1)
|
|
678
|
+
return undefined;
|
|
679
|
+
return [t, u];
|
|
680
|
+
}
|
|
681
|
+
/** Parameter of `p` projected on segment ab when it lies within `tol`. */
|
|
682
|
+
function projectWithin(p, a, b, tol) {
|
|
683
|
+
var dx = b.x - a.x;
|
|
684
|
+
var dy = b.y - a.y;
|
|
685
|
+
var len2 = dx * dx + dy * dy;
|
|
686
|
+
if (!(len2 > 0))
|
|
687
|
+
return undefined;
|
|
688
|
+
var t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / len2;
|
|
689
|
+
if (t < 0 || t > 1)
|
|
690
|
+
return undefined;
|
|
691
|
+
var d = Math.hypot(p.x - (a.x + dx * t), p.y - (a.y + dy * t));
|
|
692
|
+
return d <= tol ? t : undefined;
|
|
693
|
+
}
|
|
694
|
+
/** Removes edges that end in a vertex of degree one, repeatedly. */
|
|
695
|
+
function pruneDangling(graph) {
|
|
696
|
+
var e_12, _a;
|
|
697
|
+
var degree = graph.out.map(function (list) { return list.length; });
|
|
698
|
+
var stack = [];
|
|
699
|
+
degree.forEach(function (d, v) {
|
|
700
|
+
if (d === 1)
|
|
701
|
+
stack.push(v);
|
|
702
|
+
});
|
|
703
|
+
while (stack.length > 0) {
|
|
704
|
+
var v = stack.pop();
|
|
705
|
+
if (degree[v] !== 1)
|
|
706
|
+
continue;
|
|
707
|
+
try {
|
|
708
|
+
for (var _b = (e_12 = void 0, __values(graph.out[v])), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
709
|
+
var h = _c.value;
|
|
710
|
+
var e = h >> 1;
|
|
711
|
+
var edge = graph.edges[e];
|
|
712
|
+
if (!edge)
|
|
713
|
+
continue;
|
|
714
|
+
graph.edges[e] = undefined;
|
|
715
|
+
var other = edge[0] === v ? edge[1] : edge[0];
|
|
716
|
+
degree[v]--;
|
|
717
|
+
degree[other]--;
|
|
718
|
+
if (degree[other] === 1)
|
|
719
|
+
stack.push(other);
|
|
720
|
+
break;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
catch (e_12_1) { e_12 = { error: e_12_1 }; }
|
|
724
|
+
finally {
|
|
725
|
+
try {
|
|
726
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
727
|
+
}
|
|
728
|
+
finally { if (e_12) throw e_12.error; }
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
graph.edges = graph.edges.filter(function (edge) { return edge; });
|
|
732
|
+
rebuildIds(graph);
|
|
733
|
+
}
|
|
734
|
+
function rebuildIds(graph) {
|
|
735
|
+
var e_13, _a;
|
|
736
|
+
var edges = graph.edges;
|
|
737
|
+
var out = graph.points.map(function () { return []; });
|
|
738
|
+
edges.forEach(function (_a, e) {
|
|
739
|
+
var _b = __read(_a, 2), u = _b[0], v = _b[1];
|
|
740
|
+
out[u].push(2 * e);
|
|
741
|
+
out[v].push(2 * e + 1);
|
|
742
|
+
});
|
|
743
|
+
var angle = function (h) {
|
|
744
|
+
var _a = __read(halfEdge(graph, h), 2), from = _a[0], to = _a[1];
|
|
745
|
+
var p = graph.points[from];
|
|
746
|
+
var q = graph.points[to];
|
|
747
|
+
return Math.atan2(q.y - p.y, q.x - p.x);
|
|
748
|
+
};
|
|
749
|
+
try {
|
|
750
|
+
for (var out_1 = __values(out), out_1_1 = out_1.next(); !out_1_1.done; out_1_1 = out_1.next()) {
|
|
751
|
+
var list = out_1_1.value;
|
|
752
|
+
list.sort(function (p, q) { return angle(p) - angle(q); });
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
catch (e_13_1) { e_13 = { error: e_13_1 }; }
|
|
756
|
+
finally {
|
|
757
|
+
try {
|
|
758
|
+
if (out_1_1 && !out_1_1.done && (_a = out_1.return)) _a.call(out_1);
|
|
759
|
+
}
|
|
760
|
+
finally { if (e_13) throw e_13.error; }
|
|
761
|
+
}
|
|
762
|
+
graph.out = out;
|
|
763
|
+
}
|
|
764
|
+
function halfEdge(graph, h) {
|
|
765
|
+
var edge = graph.edges[h >> 1];
|
|
766
|
+
return h & 1 ? [edge[1], edge[0]] : [edge[0], edge[1]];
|
|
767
|
+
}
|
|
768
|
+
/** Next half-edge around the face on the left of `h`. */
|
|
769
|
+
function nextHalfEdge(graph, h) {
|
|
770
|
+
var _a = __read(halfEdge(graph, h), 2), to = _a[1];
|
|
771
|
+
var list = graph.out[to];
|
|
772
|
+
var twin = h ^ 1;
|
|
773
|
+
var at = list.indexOf(twin);
|
|
774
|
+
// The neighbour clockwise from the twin keeps the face on the left.
|
|
775
|
+
return list[(at - 1 + list.length) % list.length];
|
|
776
|
+
}
|
|
777
|
+
function traceFaces(graph) {
|
|
778
|
+
var component = components(graph);
|
|
779
|
+
var faceOf = new Int32Array(graph.edges.length * 2).fill(-1);
|
|
780
|
+
var faces = [];
|
|
781
|
+
for (var start = 0; start < graph.edges.length * 2; start++) {
|
|
782
|
+
if (faceOf[start] >= 0)
|
|
783
|
+
continue;
|
|
784
|
+
var halfEdges = [];
|
|
785
|
+
var h = start;
|
|
786
|
+
while (faceOf[h] < 0 && halfEdges.length <= graph.edges.length * 2) {
|
|
787
|
+
faceOf[h] = faces.length;
|
|
788
|
+
halfEdges.push(h);
|
|
789
|
+
h = nextHalfEdge(graph, h);
|
|
790
|
+
}
|
|
791
|
+
var points = halfEdges.map(function (e) { return graph.points[halfEdge(graph, e)[0]]; });
|
|
792
|
+
faces.push({
|
|
793
|
+
halfEdges: halfEdges,
|
|
794
|
+
points: points,
|
|
795
|
+
area: signedArea(points),
|
|
796
|
+
box: boxOf(points),
|
|
797
|
+
component: component[halfEdge(graph, start)[0]]
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
return faces;
|
|
801
|
+
}
|
|
802
|
+
function components(graph) {
|
|
803
|
+
var e_14, _a;
|
|
804
|
+
var id = new Array(graph.points.length).fill(-1);
|
|
805
|
+
var next = 0;
|
|
806
|
+
for (var v = 0; v < graph.points.length; v++) {
|
|
807
|
+
if (id[v] >= 0 || graph.out[v].length === 0)
|
|
808
|
+
continue;
|
|
809
|
+
var stack = [v];
|
|
810
|
+
id[v] = next;
|
|
811
|
+
while (stack.length > 0) {
|
|
812
|
+
var u = stack.pop();
|
|
813
|
+
try {
|
|
814
|
+
for (var _b = (e_14 = void 0, __values(graph.out[u])), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
815
|
+
var h = _c.value;
|
|
816
|
+
var _d = __read(halfEdge(graph, h), 2), w = _d[1];
|
|
817
|
+
if (id[w] < 0) {
|
|
818
|
+
id[w] = next;
|
|
819
|
+
stack.push(w);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
catch (e_14_1) { e_14 = { error: e_14_1 }; }
|
|
824
|
+
finally {
|
|
825
|
+
try {
|
|
826
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
827
|
+
}
|
|
828
|
+
finally { if (e_14) throw e_14.error; }
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
next++;
|
|
832
|
+
}
|
|
833
|
+
return id;
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* The bounded face of another component that encloses each outer cycle
|
|
837
|
+
* (negative area) of a component: an island's outer cycle is a hole of
|
|
838
|
+
* that face.
|
|
839
|
+
*/
|
|
840
|
+
function resolveHoleOwners(faces, bounded, grid) {
|
|
841
|
+
var e_15, _a;
|
|
842
|
+
var owner = new Map();
|
|
843
|
+
var _loop_3 = function (face) {
|
|
844
|
+
if (face.area > 0)
|
|
845
|
+
return "continue";
|
|
846
|
+
var p = face.points[0];
|
|
847
|
+
var best;
|
|
848
|
+
grid.forEachAt(p, function (i) {
|
|
849
|
+
var candidate = bounded[i];
|
|
850
|
+
if (candidate.component === face.component)
|
|
851
|
+
return;
|
|
852
|
+
if (candidate.area <= -face.area)
|
|
853
|
+
return;
|
|
854
|
+
if (best && candidate.area >= best.area)
|
|
855
|
+
return;
|
|
856
|
+
if (!inBox(p, candidate.box) || !pointInPolygon(p, candidate.points)) {
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
best = candidate;
|
|
860
|
+
});
|
|
861
|
+
if (best)
|
|
862
|
+
owner.set(face, best);
|
|
863
|
+
};
|
|
864
|
+
try {
|
|
865
|
+
for (var faces_1 = __values(faces), faces_1_1 = faces_1.next(); !faces_1_1.done; faces_1_1 = faces_1.next()) {
|
|
866
|
+
var face = faces_1_1.value;
|
|
867
|
+
_loop_3(face);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
catch (e_15_1) { e_15 = { error: e_15_1 }; }
|
|
871
|
+
finally {
|
|
872
|
+
try {
|
|
873
|
+
if (faces_1_1 && !faces_1_1.done && (_a = faces_1.return)) _a.call(faces_1);
|
|
874
|
+
}
|
|
875
|
+
finally { if (e_15) throw e_15.error; }
|
|
876
|
+
}
|
|
877
|
+
return owner;
|
|
878
|
+
}
|
|
879
|
+
/** Share of the median hit density a big face needs to be hatched. */
|
|
880
|
+
var MIN_DENSITY_SHARE = 0.25;
|
|
881
|
+
/** Strokes ending on an edge that mark it as two hatches' shared edge. */
|
|
882
|
+
var MIN_CLIPPED_ENDS = 3;
|
|
883
|
+
/** Most edge-stroke pairs tested before splitting is skipped. */
|
|
884
|
+
var MAX_SPLIT_TESTS = 4000000;
|
|
885
|
+
/**
|
|
886
|
+
* Groups the selected faces into hatches: neighbours join unless the
|
|
887
|
+
* strokes stop on the edge between them without crossing it.
|
|
888
|
+
*/
|
|
889
|
+
function splitFaces(graph, faces, resolve, selected, strokes, tol) {
|
|
890
|
+
var e_16, _a, e_17, _b, e_18, _c, e_19, _d, e_20, _e;
|
|
891
|
+
var list = __spreadArray([], __read(selected), false);
|
|
892
|
+
if (!strokes || strokes.length === 0 || list.length < 2)
|
|
893
|
+
return [selected];
|
|
894
|
+
var index = new Map(list.map(function (face, i) { return [face, i]; }));
|
|
895
|
+
var faceOf = new Int32Array(graph.edges.length * 2);
|
|
896
|
+
faces.forEach(function (face, i) {
|
|
897
|
+
var e_21, _a;
|
|
898
|
+
try {
|
|
899
|
+
for (var _b = __values(face.halfEdges), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
900
|
+
var h = _c.value;
|
|
901
|
+
faceOf[h] = i;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
catch (e_21_1) { e_21 = { error: e_21_1 }; }
|
|
905
|
+
finally {
|
|
906
|
+
try {
|
|
907
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
908
|
+
}
|
|
909
|
+
finally { if (e_21) throw e_21.error; }
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
var internal = [];
|
|
913
|
+
for (var e = 0; e < graph.edges.length; e++) {
|
|
914
|
+
var a = index.get(resolve(faces[faceOf[2 * e]]));
|
|
915
|
+
var b = index.get(resolve(faces[faceOf[2 * e + 1]]));
|
|
916
|
+
if (a === undefined || b === undefined || a === b)
|
|
917
|
+
continue;
|
|
918
|
+
internal.push({ e: e, a: a, b: b });
|
|
919
|
+
}
|
|
920
|
+
if (internal.length * strokes.length > MAX_SPLIT_TESTS)
|
|
921
|
+
return [selected];
|
|
922
|
+
var parent = list.map(function (_, i) { return i; });
|
|
923
|
+
var find = function (i) {
|
|
924
|
+
while (parent[i] !== i) {
|
|
925
|
+
parent[i] = parent[parent[i]];
|
|
926
|
+
i = parent[i];
|
|
927
|
+
}
|
|
928
|
+
return i;
|
|
929
|
+
};
|
|
930
|
+
// Judge each pair of neighbouring faces on all the edges they share: a
|
|
931
|
+
// short piece of a shared outline may hold too few stroke ends alone.
|
|
932
|
+
var shared = new Map();
|
|
933
|
+
try {
|
|
934
|
+
for (var internal_1 = __values(internal), internal_1_1 = internal_1.next(); !internal_1_1.done; internal_1_1 = internal_1.next()) {
|
|
935
|
+
var _f = internal_1_1.value, e = _f.e, a = _f.a, b = _f.b;
|
|
936
|
+
var key = a < b ? "".concat(a, ",").concat(b) : "".concat(b, ",").concat(a);
|
|
937
|
+
var entry = shared.get(key);
|
|
938
|
+
if (entry)
|
|
939
|
+
entry.edges.push(e);
|
|
940
|
+
else
|
|
941
|
+
shared.set(key, { a: a, b: b, edges: [e] });
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
catch (e_16_1) { e_16 = { error: e_16_1 }; }
|
|
945
|
+
finally {
|
|
946
|
+
try {
|
|
947
|
+
if (internal_1_1 && !internal_1_1.done && (_a = internal_1.return)) _a.call(internal_1);
|
|
948
|
+
}
|
|
949
|
+
finally { if (e_16) throw e_16.error; }
|
|
950
|
+
}
|
|
951
|
+
var cuts = [];
|
|
952
|
+
try {
|
|
953
|
+
for (var _g = __values(shared.values()), _h = _g.next(); !_h.done; _h = _g.next()) {
|
|
954
|
+
var _j = _h.value, a = _j.a, b = _j.b, edges = _j.edges;
|
|
955
|
+
var segments = edges.map(function (e) {
|
|
956
|
+
var _a = __read(graph.edges[e], 2), u = _a[0], v = _a[1];
|
|
957
|
+
return [graph.points[u], graph.points[v]];
|
|
958
|
+
});
|
|
959
|
+
if (separates(segments, strokes, tol)) {
|
|
960
|
+
try {
|
|
961
|
+
for (var edges_2 = (e_18 = void 0, __values(edges)), edges_2_1 = edges_2.next(); !edges_2_1.done; edges_2_1 = edges_2.next()) {
|
|
962
|
+
var e = edges_2_1.value;
|
|
963
|
+
cuts.push({ e: e, a: a, b: b });
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
catch (e_18_1) { e_18 = { error: e_18_1 }; }
|
|
967
|
+
finally {
|
|
968
|
+
try {
|
|
969
|
+
if (edges_2_1 && !edges_2_1.done && (_c = edges_2.return)) _c.call(edges_2);
|
|
970
|
+
}
|
|
971
|
+
finally { if (e_18) throw e_18.error; }
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
else {
|
|
975
|
+
parent[find(a)] = find(b);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
catch (e_17_1) { e_17 = { error: e_17_1 }; }
|
|
980
|
+
finally {
|
|
981
|
+
try {
|
|
982
|
+
if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
|
|
983
|
+
}
|
|
984
|
+
finally { if (e_17) throw e_17.error; }
|
|
985
|
+
}
|
|
986
|
+
// Loops of one hatch picked on both sides of an axis are clipped there
|
|
987
|
+
// too, but they meet along that one straight line. Two hatches that
|
|
988
|
+
// touch share a bent piece of outline instead.
|
|
989
|
+
// Repeat with the merged parts: four loops around a cross of axes join
|
|
990
|
+
// in pairs first, then the pairs along the other axis.
|
|
991
|
+
for (var merged = true; merged;) {
|
|
992
|
+
merged = false;
|
|
993
|
+
var byPair = new Map();
|
|
994
|
+
try {
|
|
995
|
+
for (var cuts_1 = (e_19 = void 0, __values(cuts)), cuts_1_1 = cuts_1.next(); !cuts_1_1.done; cuts_1_1 = cuts_1.next()) {
|
|
996
|
+
var _k = cuts_1_1.value, e = _k.e, a = _k.a, b = _k.b;
|
|
997
|
+
var ra = find(a);
|
|
998
|
+
var rb = find(b);
|
|
999
|
+
if (ra === rb)
|
|
1000
|
+
continue;
|
|
1001
|
+
var key = ra < rb ? "".concat(ra, ",").concat(rb) : "".concat(rb, ",").concat(ra);
|
|
1002
|
+
var pair = byPair.get(key);
|
|
1003
|
+
if (pair)
|
|
1004
|
+
pair.push(e);
|
|
1005
|
+
else
|
|
1006
|
+
byPair.set(key, [e]);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
catch (e_19_1) { e_19 = { error: e_19_1 }; }
|
|
1010
|
+
finally {
|
|
1011
|
+
try {
|
|
1012
|
+
if (cuts_1_1 && !cuts_1_1.done && (_d = cuts_1.return)) _d.call(cuts_1);
|
|
1013
|
+
}
|
|
1014
|
+
finally { if (e_19) throw e_19.error; }
|
|
1015
|
+
}
|
|
1016
|
+
try {
|
|
1017
|
+
for (var byPair_1 = (e_20 = void 0, __values(byPair)), byPair_1_1 = byPair_1.next(); !byPair_1_1.done; byPair_1_1 = byPair_1.next()) {
|
|
1018
|
+
var _l = __read(byPair_1_1.value, 2), key = _l[0], edges = _l[1];
|
|
1019
|
+
var _m = __read(key.split(',').map(Number), 2), ra = _m[0], rb = _m[1];
|
|
1020
|
+
if (isStraightCut(graph, edges, tol)) {
|
|
1021
|
+
parent[ra] = rb;
|
|
1022
|
+
merged = true;
|
|
1023
|
+
break;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
catch (e_20_1) { e_20 = { error: e_20_1 }; }
|
|
1028
|
+
finally {
|
|
1029
|
+
try {
|
|
1030
|
+
if (byPair_1_1 && !byPair_1_1.done && (_e = byPair_1.return)) _e.call(byPair_1);
|
|
1031
|
+
}
|
|
1032
|
+
finally { if (e_20) throw e_20.error; }
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
var groups = new Map();
|
|
1036
|
+
list.forEach(function (face, i) {
|
|
1037
|
+
var root = find(i);
|
|
1038
|
+
var group = groups.get(root);
|
|
1039
|
+
if (!group)
|
|
1040
|
+
groups.set(root, (group = new Set()));
|
|
1041
|
+
group.add(face);
|
|
1042
|
+
});
|
|
1043
|
+
return __spreadArray([], __read(groups.values()), false);
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* True when `edges` lie on one straight line: an axis or grid line drawn
|
|
1047
|
+
* across the loops of one hatch. Two hatches that touch share a bent piece
|
|
1048
|
+
* of outline (a notch, a recess) instead.
|
|
1049
|
+
*/
|
|
1050
|
+
function isStraightCut(graph, edges, tol) {
|
|
1051
|
+
var e_22, _a, e_23, _b, e_24, _c;
|
|
1052
|
+
var p;
|
|
1053
|
+
var q;
|
|
1054
|
+
var best = 0;
|
|
1055
|
+
try {
|
|
1056
|
+
// The longest edge fixes the direction most reliably.
|
|
1057
|
+
for (var edges_3 = __values(edges), edges_3_1 = edges_3.next(); !edges_3_1.done; edges_3_1 = edges_3.next()) {
|
|
1058
|
+
var e = edges_3_1.value;
|
|
1059
|
+
var _d = __read(graph.edges[e], 2), u = _d[0], v = _d[1];
|
|
1060
|
+
var a = graph.points[u];
|
|
1061
|
+
var b = graph.points[v];
|
|
1062
|
+
var len = Math.hypot(b.x - a.x, b.y - a.y);
|
|
1063
|
+
if (len > best) {
|
|
1064
|
+
best = len;
|
|
1065
|
+
p = a;
|
|
1066
|
+
q = b;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
catch (e_22_1) { e_22 = { error: e_22_1 }; }
|
|
1071
|
+
finally {
|
|
1072
|
+
try {
|
|
1073
|
+
if (edges_3_1 && !edges_3_1.done && (_a = edges_3.return)) _a.call(edges_3);
|
|
1074
|
+
}
|
|
1075
|
+
finally { if (e_22) throw e_22.error; }
|
|
1076
|
+
}
|
|
1077
|
+
if (!p || !q || !(best > 0))
|
|
1078
|
+
return false;
|
|
1079
|
+
var ux = (q.x - p.x) / best;
|
|
1080
|
+
var uy = (q.y - p.y) / best;
|
|
1081
|
+
try {
|
|
1082
|
+
for (var edges_4 = __values(edges), edges_4_1 = edges_4.next(); !edges_4_1.done; edges_4_1 = edges_4.next()) {
|
|
1083
|
+
var e = edges_4_1.value;
|
|
1084
|
+
try {
|
|
1085
|
+
for (var _e = (e_24 = void 0, __values(graph.edges[e])), _f = _e.next(); !_f.done; _f = _e.next()) {
|
|
1086
|
+
var v = _f.value;
|
|
1087
|
+
var r = graph.points[v];
|
|
1088
|
+
if (Math.abs(-uy * (r.x - p.x) + ux * (r.y - p.y)) > tol)
|
|
1089
|
+
return false;
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
catch (e_24_1) { e_24 = { error: e_24_1 }; }
|
|
1093
|
+
finally {
|
|
1094
|
+
try {
|
|
1095
|
+
if (_f && !_f.done && (_c = _e.return)) _c.call(_e);
|
|
1096
|
+
}
|
|
1097
|
+
finally { if (e_24) throw e_24.error; }
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
catch (e_23_1) { e_23 = { error: e_23_1 }; }
|
|
1102
|
+
finally {
|
|
1103
|
+
try {
|
|
1104
|
+
if (edges_4_1 && !edges_4_1.done && (_b = edges_4.return)) _b.call(edges_4);
|
|
1105
|
+
}
|
|
1106
|
+
finally { if (e_23) throw e_23.error; }
|
|
1107
|
+
}
|
|
1108
|
+
return true;
|
|
1109
|
+
}
|
|
1110
|
+
/**
|
|
1111
|
+
* True when strokes end on the shared edges from their sides and none
|
|
1112
|
+
* crosses them: the edges are where two hatches were each clipped.
|
|
1113
|
+
*/
|
|
1114
|
+
function separates(edges, strokes, tol) {
|
|
1115
|
+
var e_25, _a, e_26, _b;
|
|
1116
|
+
var ends = 0;
|
|
1117
|
+
try {
|
|
1118
|
+
for (var edges_5 = __values(edges), edges_5_1 = edges_5.next(); !edges_5_1.done; edges_5_1 = edges_5.next()) {
|
|
1119
|
+
var _c = __read(edges_5_1.value, 2), p = _c[0], q = _c[1];
|
|
1120
|
+
var minX = Math.min(p.x, q.x) - tol;
|
|
1121
|
+
var maxX = Math.max(p.x, q.x) + tol;
|
|
1122
|
+
var minY = Math.min(p.y, q.y) - tol;
|
|
1123
|
+
var maxY = Math.max(p.y, q.y) + tol;
|
|
1124
|
+
try {
|
|
1125
|
+
for (var strokes_1 = (e_26 = void 0, __values(strokes)), strokes_1_1 = strokes_1.next(); !strokes_1_1.done; strokes_1_1 = strokes_1.next()) {
|
|
1126
|
+
var _d = __read(strokes_1_1.value, 2), a = _d[0], b = _d[1];
|
|
1127
|
+
if (Math.max(a.x, b.x) < minX ||
|
|
1128
|
+
Math.min(a.x, b.x) > maxX ||
|
|
1129
|
+
Math.max(a.y, b.y) < minY ||
|
|
1130
|
+
Math.min(a.y, b.y) > maxY) {
|
|
1131
|
+
continue;
|
|
1132
|
+
}
|
|
1133
|
+
var cross = crossing(a, b, p, q);
|
|
1134
|
+
if (cross) {
|
|
1135
|
+
var len = Math.hypot(b.x - a.x, b.y - a.y);
|
|
1136
|
+
var margin = len > 0 ? tol / len : 1;
|
|
1137
|
+
// Crossing away from the stroke's ends: it runs across the edge.
|
|
1138
|
+
if (cross[0] > margin && cross[0] < 1 - margin)
|
|
1139
|
+
return false;
|
|
1140
|
+
}
|
|
1141
|
+
if (distanceToSegment(a, p, q) <= tol ||
|
|
1142
|
+
distanceToSegment(b, p, q) <= tol) {
|
|
1143
|
+
ends++;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
catch (e_26_1) { e_26 = { error: e_26_1 }; }
|
|
1148
|
+
finally {
|
|
1149
|
+
try {
|
|
1150
|
+
if (strokes_1_1 && !strokes_1_1.done && (_b = strokes_1.return)) _b.call(strokes_1);
|
|
1151
|
+
}
|
|
1152
|
+
finally { if (e_26) throw e_26.error; }
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
catch (e_25_1) { e_25 = { error: e_25_1 }; }
|
|
1157
|
+
finally {
|
|
1158
|
+
try {
|
|
1159
|
+
if (edges_5_1 && !edges_5_1.done && (_a = edges_5.return)) _a.call(edges_5);
|
|
1160
|
+
}
|
|
1161
|
+
finally { if (e_25) throw e_25.error; }
|
|
1162
|
+
}
|
|
1163
|
+
return ends >= MIN_CLIPPED_ENDS;
|
|
1164
|
+
}
|
|
1165
|
+
/** Loops along the edges between selected and unselected faces. */
|
|
1166
|
+
function unionOutline(graph, faces, isSelected, tol) {
|
|
1167
|
+
var faceOf = new Int32Array(graph.edges.length * 2);
|
|
1168
|
+
faces.forEach(function (face, i) {
|
|
1169
|
+
var e_27, _a;
|
|
1170
|
+
try {
|
|
1171
|
+
for (var _b = __values(face.halfEdges), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
1172
|
+
var h = _c.value;
|
|
1173
|
+
faceOf[h] = i;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
catch (e_27_1) { e_27 = { error: e_27_1 }; }
|
|
1177
|
+
finally {
|
|
1178
|
+
try {
|
|
1179
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
1180
|
+
}
|
|
1181
|
+
finally { if (e_27) throw e_27.error; }
|
|
1182
|
+
}
|
|
1183
|
+
});
|
|
1184
|
+
var onOutline = function (h) {
|
|
1185
|
+
return isSelected(faces[faceOf[h]]) && !isSelected(faces[faceOf[h ^ 1]]);
|
|
1186
|
+
};
|
|
1187
|
+
var used = new Uint8Array(graph.edges.length * 2);
|
|
1188
|
+
var loops = [];
|
|
1189
|
+
for (var start = 0; start < graph.edges.length * 2; start++) {
|
|
1190
|
+
if (used[start] || !onOutline(start))
|
|
1191
|
+
continue;
|
|
1192
|
+
var loop = [];
|
|
1193
|
+
var h = start;
|
|
1194
|
+
var guard = graph.edges.length * 2 + 1;
|
|
1195
|
+
while (!used[h] && guard-- > 0) {
|
|
1196
|
+
used[h] = 1;
|
|
1197
|
+
loop.push(graph.points[halfEdge(graph, h)[0]]);
|
|
1198
|
+
// Turn past edges that lie between two selected faces.
|
|
1199
|
+
var g = nextHalfEdge(graph, h);
|
|
1200
|
+
var spin = graph.edges.length * 2 + 1;
|
|
1201
|
+
while (!onOutline(g) && spin-- > 0)
|
|
1202
|
+
g = nextHalfEdge(graph, g ^ 1);
|
|
1203
|
+
h = g;
|
|
1204
|
+
}
|
|
1205
|
+
var simple = simplify(loop, tol * 0.1);
|
|
1206
|
+
if (simple.length >= 3 && Math.abs(signedArea(simple)) > tol * tol) {
|
|
1207
|
+
loops.push(simple);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
return loops.length > 0 ? loops : undefined;
|
|
1211
|
+
}
|
|
1212
|
+
/** Drops vertices on the straight line between their neighbours. */
|
|
1213
|
+
function simplify(points, tol) {
|
|
1214
|
+
var out = points;
|
|
1215
|
+
for (var pass = 0; pass < 4; pass++) {
|
|
1216
|
+
var next = out.filter(function (p, i) {
|
|
1217
|
+
var a = out[(i - 1 + out.length) % out.length];
|
|
1218
|
+
var b = out[(i + 1) % out.length];
|
|
1219
|
+
return distanceToSegment(p, a, b) > tol;
|
|
1220
|
+
});
|
|
1221
|
+
if (next.length === out.length || next.length < 3)
|
|
1222
|
+
break;
|
|
1223
|
+
out = next;
|
|
1224
|
+
}
|
|
1225
|
+
return out;
|
|
1226
|
+
}
|
|
1227
|
+
function distanceToSegment(p, a, b) {
|
|
1228
|
+
var dx = b.x - a.x;
|
|
1229
|
+
var dy = b.y - a.y;
|
|
1230
|
+
var len2 = dx * dx + dy * dy;
|
|
1231
|
+
var t = len2 > 0 ? ((p.x - a.x) * dx + (p.y - a.y) * dy) / len2 : 0;
|
|
1232
|
+
t = Math.max(0, Math.min(1, t));
|
|
1233
|
+
return Math.hypot(p.x - (a.x + dx * t), p.y - (a.y + dy * t));
|
|
1234
|
+
}
|
|
1235
|
+
function signedArea(points) {
|
|
1236
|
+
var sum = 0;
|
|
1237
|
+
for (var i = 0; i < points.length; i++) {
|
|
1238
|
+
var a = points[i];
|
|
1239
|
+
var b = points[(i + 1) % points.length];
|
|
1240
|
+
sum += a.x * b.y - b.x * a.y;
|
|
1241
|
+
}
|
|
1242
|
+
return sum / 2;
|
|
1243
|
+
}
|
|
1244
|
+
function boxOf(points) {
|
|
1245
|
+
var e_28, _a;
|
|
1246
|
+
var box = {
|
|
1247
|
+
minX: Infinity,
|
|
1248
|
+
minY: Infinity,
|
|
1249
|
+
maxX: -Infinity,
|
|
1250
|
+
maxY: -Infinity
|
|
1251
|
+
};
|
|
1252
|
+
try {
|
|
1253
|
+
for (var points_1 = __values(points), points_1_1 = points_1.next(); !points_1_1.done; points_1_1 = points_1.next()) {
|
|
1254
|
+
var p = points_1_1.value;
|
|
1255
|
+
box.minX = Math.min(box.minX, p.x);
|
|
1256
|
+
box.minY = Math.min(box.minY, p.y);
|
|
1257
|
+
box.maxX = Math.max(box.maxX, p.x);
|
|
1258
|
+
box.maxY = Math.max(box.maxY, p.y);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
catch (e_28_1) { e_28 = { error: e_28_1 }; }
|
|
1262
|
+
finally {
|
|
1263
|
+
try {
|
|
1264
|
+
if (points_1_1 && !points_1_1.done && (_a = points_1.return)) _a.call(points_1);
|
|
1265
|
+
}
|
|
1266
|
+
finally { if (e_28) throw e_28.error; }
|
|
1267
|
+
}
|
|
1268
|
+
return box;
|
|
1269
|
+
}
|
|
1270
|
+
function inBox(p, box) {
|
|
1271
|
+
return (p.x >= box.minX && p.x <= box.maxX && p.y >= box.minY && p.y <= box.maxY);
|
|
1272
|
+
}
|
|
1273
|
+
function pointInPolygon(p, polygon) {
|
|
1274
|
+
var inside = false;
|
|
1275
|
+
for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
|
1276
|
+
var a = polygon[i];
|
|
1277
|
+
var b = polygon[j];
|
|
1278
|
+
if (a.y > p.y !== b.y > p.y &&
|
|
1279
|
+
p.x < ((b.x - a.x) * (p.y - a.y)) / (b.y - a.y) + a.x) {
|
|
1280
|
+
inside = !inside;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
return inside;
|
|
1284
|
+
}
|
|
1285
|
+
//# sourceMappingURL=pdfHatchFaces.js.map
|