@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,1023 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recognizes exploded dimensions (arrowheads or ticks, dimension line,
|
|
3
|
+
* extension lines and text) in imported PDF geometry.
|
|
4
|
+
*
|
|
5
|
+
* Pure geometry: callers describe lines, closed polylines, circles and texts
|
|
6
|
+
* with plain data, so the recognizer is unit-testable without the data model.
|
|
7
|
+
*/
|
|
8
|
+
var __assign = (this && this.__assign) || function () {
|
|
9
|
+
__assign = Object.assign || function(t) {
|
|
10
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
11
|
+
s = arguments[i];
|
|
12
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
13
|
+
t[p] = s[p];
|
|
14
|
+
}
|
|
15
|
+
return t;
|
|
16
|
+
};
|
|
17
|
+
return __assign.apply(this, arguments);
|
|
18
|
+
};
|
|
19
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
20
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
21
|
+
if (!m) return o;
|
|
22
|
+
var i = m.call(o), r, ar = [], e;
|
|
23
|
+
try {
|
|
24
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
25
|
+
}
|
|
26
|
+
catch (error) { e = { error: error }; }
|
|
27
|
+
finally {
|
|
28
|
+
try {
|
|
29
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
30
|
+
}
|
|
31
|
+
finally { if (e) throw e.error; }
|
|
32
|
+
}
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
36
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
37
|
+
if (ar || !(i in from)) {
|
|
38
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
39
|
+
ar[i] = from[i];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
43
|
+
};
|
|
44
|
+
var __values = (this && this.__values) || function(o) {
|
|
45
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
46
|
+
if (m) return m.call(o);
|
|
47
|
+
if (o && typeof o.length === "number") return {
|
|
48
|
+
next: function () {
|
|
49
|
+
if (o && i >= o.length) o = void 0;
|
|
50
|
+
return { value: o && o[i++], done: !o };
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
54
|
+
};
|
|
55
|
+
import { cross, dist, dot, sub } from './pdfRecGeometry';
|
|
56
|
+
function unit(v) {
|
|
57
|
+
var len = Math.hypot(v.x, v.y);
|
|
58
|
+
return len > 0 ? { x: v.x / len, y: v.y / len } : { x: 0, y: 0 };
|
|
59
|
+
}
|
|
60
|
+
function lerp(a, b, t) {
|
|
61
|
+
return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
|
|
62
|
+
}
|
|
63
|
+
function median(values) {
|
|
64
|
+
if (values.length === 0)
|
|
65
|
+
return 0;
|
|
66
|
+
var sorted = __spreadArray([], __read(values), false).sort(function (a, b) { return a - b; });
|
|
67
|
+
return sorted[Math.floor(sorted.length / 2)];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Reads an arrowhead from a closed triangle: the sharpest corner is the tip,
|
|
71
|
+
* the others form the base. Rejects shapes that are not slender triangles.
|
|
72
|
+
*/
|
|
73
|
+
export function pdfArrowFromPolygon(vertices) {
|
|
74
|
+
var pts = __spreadArray([], __read(vertices), false);
|
|
75
|
+
if (pts.length === 4 && dist(pts[0], pts[3]) < 1e-9)
|
|
76
|
+
pts.pop();
|
|
77
|
+
if (pts.length !== 3)
|
|
78
|
+
return undefined;
|
|
79
|
+
var angleAt = function (i) {
|
|
80
|
+
var a = sub(pts[(i + 1) % 3], pts[i]);
|
|
81
|
+
var b = sub(pts[(i + 2) % 3], pts[i]);
|
|
82
|
+
return Math.atan2(Math.abs(cross(a, b)), dot(a, b));
|
|
83
|
+
};
|
|
84
|
+
var angles = [0, 1, 2].map(angleAt);
|
|
85
|
+
var tipIndex = angles.indexOf(Math.min.apply(Math, __spreadArray([], __read(angles), false)));
|
|
86
|
+
// Dimension arrows are slender: tip angle typically 15°–40°.
|
|
87
|
+
if (angles[tipIndex] > (50 * Math.PI) / 180)
|
|
88
|
+
return undefined;
|
|
89
|
+
var tip = pts[tipIndex];
|
|
90
|
+
var baseMid = lerp(pts[(tipIndex + 1) % 3], pts[(tipIndex + 2) % 3], 0.5);
|
|
91
|
+
var size = dist(tip, baseMid);
|
|
92
|
+
if (!(size > 0))
|
|
93
|
+
return undefined;
|
|
94
|
+
return { tip: tip, direction: unit(sub(tip, baseMid)), size: size };
|
|
95
|
+
}
|
|
96
|
+
/** First number in a dimension text, e.g. `Ø25` → 25, `1,200` → 1200. */
|
|
97
|
+
export function parsePdfDimensionValue(text) {
|
|
98
|
+
var match = /\d+(?:[.,]\d+)*/.exec(text.replace(/\s+/g, ''));
|
|
99
|
+
if (!match)
|
|
100
|
+
return undefined;
|
|
101
|
+
var raw = match[0];
|
|
102
|
+
if (/^\d{1,3}(,\d{3})+$/.test(raw))
|
|
103
|
+
raw = raw.replace(/,/g, '');
|
|
104
|
+
else
|
|
105
|
+
raw = raw.replace(',', '.');
|
|
106
|
+
var value = Number.parseFloat(raw);
|
|
107
|
+
return Number.isFinite(value) ? value : undefined;
|
|
108
|
+
}
|
|
109
|
+
/** Classifies a dimension text prefix. */
|
|
110
|
+
function radialKind(text) {
|
|
111
|
+
var t = text.trim();
|
|
112
|
+
if (/^(Ø|⌀|ø|%%c|%%C|\\U\+2205)/.test(t))
|
|
113
|
+
return 'diameter';
|
|
114
|
+
if (/^R\s*\d/i.test(t))
|
|
115
|
+
return 'radius';
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Finds linear, radius and diameter dimensions.
|
|
120
|
+
*
|
|
121
|
+
* Linear: two terminators whose tips share their axis (arrows pointing
|
|
122
|
+
* apart, or together for small dimensions), a value text beside them, and
|
|
123
|
+
* optional extension lines through each tip. Pairs are taken shortest
|
|
124
|
+
* first so chained dimensions sharing extension lines stay separate.
|
|
125
|
+
*
|
|
126
|
+
* Radial: an arrow whose tip lies on a circle and points along its radius,
|
|
127
|
+
* with an `R…` or `Ø…` text nearby.
|
|
128
|
+
*
|
|
129
|
+
* @param input - Candidate shapes.
|
|
130
|
+
* @param options - Tolerances.
|
|
131
|
+
*/
|
|
132
|
+
export function recognizePdfDimensions(input, options) {
|
|
133
|
+
var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f;
|
|
134
|
+
var _g, _h, _j;
|
|
135
|
+
if (options === void 0) { options = {}; }
|
|
136
|
+
var arrows = [];
|
|
137
|
+
try {
|
|
138
|
+
for (var _k = __values(input.polygons), _l = _k.next(); !_l.done; _l = _k.next()) {
|
|
139
|
+
var polygon = _l.value;
|
|
140
|
+
var arrow = pdfArrowFromPolygon(polygon.vertices);
|
|
141
|
+
if (arrow)
|
|
142
|
+
arrows.push(__assign({ ids: [polygon.id] }, arrow));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
146
|
+
finally {
|
|
147
|
+
try {
|
|
148
|
+
if (_l && !_l.done && (_a = _k.return)) _a.call(_k);
|
|
149
|
+
}
|
|
150
|
+
finally { if (e_1) throw e_1.error; }
|
|
151
|
+
}
|
|
152
|
+
var textHeights = input.texts.map(function (t) { return t.height; }).filter(function (h) { return h > 0; });
|
|
153
|
+
var refSize = median(arrows.map(function (a) { return a.size; })) || median(textHeights) || 1;
|
|
154
|
+
var tol = (_g = options.tolerance) !== null && _g !== void 0 ? _g : Math.max(refSize * 0.02, 1e-6);
|
|
155
|
+
var angleTol = (_h = options.angleTolerance) !== null && _h !== void 0 ? _h : (3 * Math.PI) / 180;
|
|
156
|
+
var sinTol = Math.sin(angleTol);
|
|
157
|
+
var usedSegments = new Set();
|
|
158
|
+
var usedTexts = new Set();
|
|
159
|
+
var usedArrows = new Set();
|
|
160
|
+
// Chained dimensions share extension lines, so those may be referenced
|
|
161
|
+
// again (they are consumed only once).
|
|
162
|
+
var extensionIds = new Set();
|
|
163
|
+
var results = [];
|
|
164
|
+
// Angular dimensions first: an arc with an arrow at each end, pointing
|
|
165
|
+
// along the arc, and a value text near its middle.
|
|
166
|
+
var tangentTol = Math.sin((10 * Math.PI) / 180);
|
|
167
|
+
var _loop_1 = function (arc) {
|
|
168
|
+
var e_7, _s, e_8, _t;
|
|
169
|
+
if (usedSegments.has(arc.id))
|
|
170
|
+
return "continue";
|
|
171
|
+
var at = function (angle) { return ({
|
|
172
|
+
x: arc.center.x + arc.radius * Math.cos(angle),
|
|
173
|
+
y: arc.center.y + arc.radius * Math.sin(angle)
|
|
174
|
+
}); };
|
|
175
|
+
var sweep = arc.endAngle - arc.startAngle;
|
|
176
|
+
if (sweep <= 0)
|
|
177
|
+
sweep += Math.PI * 2;
|
|
178
|
+
var ends = [at(arc.startAngle), at(arc.startAngle + sweep)];
|
|
179
|
+
var endArrows = ends.map(function (end) {
|
|
180
|
+
return arrows.find(function (a) {
|
|
181
|
+
if (usedArrows.has(a) || dist(a.tip, end) > tol * 4)
|
|
182
|
+
return false;
|
|
183
|
+
var radial = unit(sub(end, arc.center));
|
|
184
|
+
return Math.abs(dot(a.direction, radial)) <= tangentTol;
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
if (!endArrows[0] || !endArrows[1] || endArrows[0] === endArrows[1]) {
|
|
188
|
+
return "continue";
|
|
189
|
+
}
|
|
190
|
+
var arcPoint = at(arc.startAngle + sweep / 2);
|
|
191
|
+
var text = nearestText(input.texts, usedTexts, arcPoint, Math.max(arc.radius * 0.8, refSize * 6), function (t) { return parsePdfDimensionValue(t.text) !== undefined; });
|
|
192
|
+
if (!text)
|
|
193
|
+
return "continue";
|
|
194
|
+
var consumed = __spreadArray(__spreadArray(__spreadArray([
|
|
195
|
+
arc.id
|
|
196
|
+
], __read(endArrows[0].ids), false), __read(endArrows[1].ids), false), __read(pdfDimTextIds(text)), false);
|
|
197
|
+
// Radial extension lines through each end; the end nearer the center
|
|
198
|
+
// is the object side.
|
|
199
|
+
var leg = function (end) {
|
|
200
|
+
var e_9, _a;
|
|
201
|
+
var radial = unit(sub(end, arc.center));
|
|
202
|
+
try {
|
|
203
|
+
for (var _b = (e_9 = void 0, __values(input.segments)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
204
|
+
var s = _c.value;
|
|
205
|
+
if (usedSegments.has(s.id) || consumed.includes(s.id))
|
|
206
|
+
continue;
|
|
207
|
+
var su = unit(sub(s.p1, s.p0));
|
|
208
|
+
if (Math.abs(cross(su, radial)) > sinTol)
|
|
209
|
+
continue;
|
|
210
|
+
if (Math.abs(cross(radial, sub(s.p0, arc.center))) > tol * 2)
|
|
211
|
+
continue;
|
|
212
|
+
if (!pointNearSegment(end, s, refSize * 2))
|
|
213
|
+
continue;
|
|
214
|
+
consumed.push(s.id);
|
|
215
|
+
return dist(s.p0, arc.center) <= dist(s.p1, arc.center) ? s.p0 : s.p1;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
catch (e_9_1) { e_9 = { error: e_9_1 }; }
|
|
219
|
+
finally {
|
|
220
|
+
try {
|
|
221
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
222
|
+
}
|
|
223
|
+
finally { if (e_9) throw e_9.error; }
|
|
224
|
+
}
|
|
225
|
+
return end;
|
|
226
|
+
};
|
|
227
|
+
var xLine1 = leg(ends[0]);
|
|
228
|
+
var xLine2 = leg(ends[1]);
|
|
229
|
+
usedArrows.add(endArrows[0]);
|
|
230
|
+
usedArrows.add(endArrows[1]);
|
|
231
|
+
try {
|
|
232
|
+
for (var _u = (e_7 = void 0, __values(pdfDimTextIds(text))), _v = _u.next(); !_v.done; _v = _u.next()) {
|
|
233
|
+
var id = _v.value;
|
|
234
|
+
usedTexts.add(id);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
|
238
|
+
finally {
|
|
239
|
+
try {
|
|
240
|
+
if (_v && !_v.done && (_s = _u.return)) _s.call(_u);
|
|
241
|
+
}
|
|
242
|
+
finally { if (e_7) throw e_7.error; }
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
for (var consumed_1 = (e_8 = void 0, __values(consumed)), consumed_1_1 = consumed_1.next(); !consumed_1_1.done; consumed_1_1 = consumed_1.next()) {
|
|
246
|
+
var id = consumed_1_1.value;
|
|
247
|
+
usedSegments.add(id);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
|
251
|
+
finally {
|
|
252
|
+
try {
|
|
253
|
+
if (consumed_1_1 && !consumed_1_1.done && (_t = consumed_1.return)) _t.call(consumed_1);
|
|
254
|
+
}
|
|
255
|
+
finally { if (e_8) throw e_8.error; }
|
|
256
|
+
}
|
|
257
|
+
results.push({
|
|
258
|
+
kind: 'angular',
|
|
259
|
+
center: arc.center,
|
|
260
|
+
xLine1: xLine1,
|
|
261
|
+
xLine2: xLine2,
|
|
262
|
+
arcPoint: arcPoint,
|
|
263
|
+
measured: (sweep * 180) / Math.PI,
|
|
264
|
+
text: text,
|
|
265
|
+
arrowSize: endArrows[0].size,
|
|
266
|
+
consumed: consumed
|
|
267
|
+
});
|
|
268
|
+
};
|
|
269
|
+
try {
|
|
270
|
+
for (var _m = __values((_j = input.arcs) !== null && _j !== void 0 ? _j : []), _o = _m.next(); !_o.done; _o = _m.next()) {
|
|
271
|
+
var arc = _o.value;
|
|
272
|
+
_loop_1(arc);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
276
|
+
finally {
|
|
277
|
+
try {
|
|
278
|
+
if (_o && !_o.done && (_b = _m.return)) _b.call(_m);
|
|
279
|
+
}
|
|
280
|
+
finally { if (e_2) throw e_2.error; }
|
|
281
|
+
}
|
|
282
|
+
var _loop_2 = function (arrow) {
|
|
283
|
+
var e_10, _w, e_11, _x, e_12, _y;
|
|
284
|
+
try {
|
|
285
|
+
for (var _z = (e_10 = void 0, __values(input.curves)), _0 = _z.next(); !_0.done; _0 = _z.next()) {
|
|
286
|
+
var curve = _0.value;
|
|
287
|
+
var radial = sub(arrow.tip, curve.center);
|
|
288
|
+
var r = Math.hypot(radial.x, radial.y);
|
|
289
|
+
if (Math.abs(r - curve.radius) > tol * 2 || r === 0)
|
|
290
|
+
continue;
|
|
291
|
+
if (Math.abs(cross(arrow.direction, unit(radial))) > sinTol)
|
|
292
|
+
continue;
|
|
293
|
+
var text = nearestText(input.texts, usedTexts, arrow.tip, refSize * 12, function (t) { return radialKind(t.text) !== undefined; });
|
|
294
|
+
if (!text)
|
|
295
|
+
continue;
|
|
296
|
+
var kind = radialKind(text.text);
|
|
297
|
+
var leaders = input.segments.filter(function (s) {
|
|
298
|
+
return !usedSegments.has(s.id) &&
|
|
299
|
+
(dist(s.p0, arrow.tip) <= tol * 2 ||
|
|
300
|
+
dist(s.p1, arrow.tip) <= tol * 2 ||
|
|
301
|
+
pointNearSegment(arrow.tip, s, tol * 2));
|
|
302
|
+
});
|
|
303
|
+
try {
|
|
304
|
+
for (var leaders_1 = (e_11 = void 0, __values(leaders)), leaders_1_1 = leaders_1.next(); !leaders_1_1.done; leaders_1_1 = leaders_1.next()) {
|
|
305
|
+
var s = leaders_1_1.value;
|
|
306
|
+
usedSegments.add(s.id);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
catch (e_11_1) { e_11 = { error: e_11_1 }; }
|
|
310
|
+
finally {
|
|
311
|
+
try {
|
|
312
|
+
if (leaders_1_1 && !leaders_1_1.done && (_x = leaders_1.return)) _x.call(leaders_1);
|
|
313
|
+
}
|
|
314
|
+
finally { if (e_11) throw e_11.error; }
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
for (var _1 = (e_12 = void 0, __values(pdfDimTextIds(text))), _2 = _1.next(); !_2.done; _2 = _1.next()) {
|
|
318
|
+
var id = _2.value;
|
|
319
|
+
usedTexts.add(id);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
catch (e_12_1) { e_12 = { error: e_12_1 }; }
|
|
323
|
+
finally {
|
|
324
|
+
try {
|
|
325
|
+
if (_2 && !_2.done && (_y = _1.return)) _y.call(_1);
|
|
326
|
+
}
|
|
327
|
+
finally { if (e_12) throw e_12.error; }
|
|
328
|
+
}
|
|
329
|
+
usedArrows.add(arrow);
|
|
330
|
+
results.push({
|
|
331
|
+
kind: kind,
|
|
332
|
+
center: curve.center,
|
|
333
|
+
chordPoint: arrow.tip,
|
|
334
|
+
radius: curve.radius,
|
|
335
|
+
leaderLength: dist(arrow.tip, text.center),
|
|
336
|
+
measured: kind === 'diameter' ? curve.radius * 2 : curve.radius,
|
|
337
|
+
text: text,
|
|
338
|
+
arrowSize: arrow.size,
|
|
339
|
+
consumed: __spreadArray(__spreadArray(__spreadArray([], __read(arrow.ids), false), __read(leaders.map(function (s) { return s.id; })), false), __read(pdfDimTextIds(text)), false)
|
|
340
|
+
});
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
catch (e_10_1) { e_10 = { error: e_10_1 }; }
|
|
345
|
+
finally {
|
|
346
|
+
try {
|
|
347
|
+
if (_0 && !_0.done && (_w = _z.return)) _w.call(_z);
|
|
348
|
+
}
|
|
349
|
+
finally { if (e_10) throw e_10.error; }
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
try {
|
|
353
|
+
// Radial dimensions next: their arrows must not pair up as linear ones.
|
|
354
|
+
for (var arrows_1 = __values(arrows), arrows_1_1 = arrows_1.next(); !arrows_1_1.done; arrows_1_1 = arrows_1.next()) {
|
|
355
|
+
var arrow = arrows_1_1.value;
|
|
356
|
+
_loop_2(arrow);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
360
|
+
finally {
|
|
361
|
+
try {
|
|
362
|
+
if (arrows_1_1 && !arrows_1_1.done && (_c = arrows_1.return)) _c.call(arrows_1);
|
|
363
|
+
}
|
|
364
|
+
finally { if (e_3) throw e_3.error; }
|
|
365
|
+
}
|
|
366
|
+
// Ticks: short oblique lines centered near the ends of a longer line.
|
|
367
|
+
var ticks = [];
|
|
368
|
+
var shortLimit = Math.max(median(textHeights), refSize) * 1.5;
|
|
369
|
+
var shorts = input.segments.filter(function (s) { return dist(s.p0, s.p1) <= shortLimit; });
|
|
370
|
+
try {
|
|
371
|
+
for (var _p = __values(input.segments), _q = _p.next(); !_q.done; _q = _p.next()) {
|
|
372
|
+
var line = _q.value;
|
|
373
|
+
var length_1 = dist(line.p0, line.p1);
|
|
374
|
+
if (length_1 <= shortLimit)
|
|
375
|
+
continue;
|
|
376
|
+
var u = unit(sub(line.p1, line.p0));
|
|
377
|
+
try {
|
|
378
|
+
for (var shorts_1 = (e_5 = void 0, __values(shorts)), shorts_1_1 = shorts_1.next(); !shorts_1_1.done; shorts_1_1 = shorts_1.next()) {
|
|
379
|
+
var tick = shorts_1_1.value;
|
|
380
|
+
var mid = lerp(tick.p0, tick.p1, 0.5);
|
|
381
|
+
if (Math.abs(cross(u, sub(mid, line.p0))) > tol * 2)
|
|
382
|
+
continue;
|
|
383
|
+
var along = dot(sub(mid, line.p0), u);
|
|
384
|
+
var nearEnd = Math.min(Math.abs(along), Math.abs(along - length_1));
|
|
385
|
+
if (nearEnd > shortLimit)
|
|
386
|
+
continue;
|
|
387
|
+
var tu = unit(sub(tick.p1, tick.p0));
|
|
388
|
+
var angle = Math.acos(Math.min(1, Math.abs(dot(tu, u))));
|
|
389
|
+
if (angle < Math.PI / 6 || angle > Math.PI / 3)
|
|
390
|
+
continue;
|
|
391
|
+
ticks.push({
|
|
392
|
+
ids: [tick.id],
|
|
393
|
+
tip: mid,
|
|
394
|
+
size: dist(tick.p0, tick.p1) / 2,
|
|
395
|
+
line: line
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
400
|
+
finally {
|
|
401
|
+
try {
|
|
402
|
+
if (shorts_1_1 && !shorts_1_1.done && (_e = shorts_1.return)) _e.call(shorts_1);
|
|
403
|
+
}
|
|
404
|
+
finally { if (e_5) throw e_5.error; }
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
409
|
+
finally {
|
|
410
|
+
try {
|
|
411
|
+
if (_q && !_q.done && (_d = _p.return)) _d.call(_p);
|
|
412
|
+
}
|
|
413
|
+
finally { if (e_4) throw e_4.error; }
|
|
414
|
+
}
|
|
415
|
+
var pairs = [];
|
|
416
|
+
var free = arrows.filter(function (a) { return !usedArrows.has(a); });
|
|
417
|
+
for (var i = 0; i < free.length; i++) {
|
|
418
|
+
for (var j = i + 1; j < free.length; j++) {
|
|
419
|
+
var a = free[i];
|
|
420
|
+
var b = free[j];
|
|
421
|
+
if (Math.max(a.size, b.size) > Math.min(a.size, b.size) * 1.5)
|
|
422
|
+
continue;
|
|
423
|
+
var d = sub(b.tip, a.tip);
|
|
424
|
+
var length_2 = Math.hypot(d.x, d.y);
|
|
425
|
+
if (length_2 <= tol * 4)
|
|
426
|
+
continue;
|
|
427
|
+
var u = unit(d);
|
|
428
|
+
if (Math.abs(cross(a.direction, u)) > sinTol)
|
|
429
|
+
continue;
|
|
430
|
+
if (Math.abs(cross(b.direction, u)) > sinTol)
|
|
431
|
+
continue;
|
|
432
|
+
// Pointing apart (inside arrows) or toward each other (outside arrows).
|
|
433
|
+
if (dot(a.direction, u) * dot(b.direction, u) >= 0)
|
|
434
|
+
continue;
|
|
435
|
+
pairs.push({ a: a, b: b, length: length_2 });
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
// Tick pairs share one dimension line.
|
|
439
|
+
for (var i = 0; i < ticks.length; i++) {
|
|
440
|
+
for (var j = i + 1; j < ticks.length; j++) {
|
|
441
|
+
if (ticks[i].line !== ticks[j].line)
|
|
442
|
+
continue;
|
|
443
|
+
var length_3 = dist(ticks[i].tip, ticks[j].tip);
|
|
444
|
+
if (length_3 <= tol * 4)
|
|
445
|
+
continue;
|
|
446
|
+
pairs.push({ a: ticks[i], b: ticks[j], length: length_3 });
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
pairs.sort(function (p, q) { return p.length - q.length; });
|
|
450
|
+
var _loop_3 = function (a, b, length_4) {
|
|
451
|
+
var e_13, _3, e_14, _4, e_15, _5;
|
|
452
|
+
if (usedArrows.has(a) || usedArrows.has(b))
|
|
453
|
+
return "continue";
|
|
454
|
+
if (a.ids.some(function (id) { return usedSegments.has(id); }) ||
|
|
455
|
+
b.ids.some(function (id) { return usedSegments.has(id); })) {
|
|
456
|
+
return "continue";
|
|
457
|
+
}
|
|
458
|
+
var u = unit(sub(b.tip, a.tip));
|
|
459
|
+
var n = { x: -u.y, y: u.x };
|
|
460
|
+
var mid = lerp(a.tip, b.tip, 0.5);
|
|
461
|
+
var acceptLinearText = function (t) {
|
|
462
|
+
if (t.text !== undefined &&
|
|
463
|
+
parsePdfDimensionValue(t.text) === undefined) {
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
var rel = sub(t.center, a.tip);
|
|
467
|
+
var along = dot(rel, u);
|
|
468
|
+
var across = Math.abs(dot(rel, n));
|
|
469
|
+
return (across <= t.height * 2.5 &&
|
|
470
|
+
along >= -length_4 * 0.5 - t.height * 4 &&
|
|
471
|
+
along <= length_4 * 1.5 + t.height * 4);
|
|
472
|
+
};
|
|
473
|
+
var text = nearestText(input.texts, usedTexts, mid, Math.max(length_4 * 0.75, refSize * 6), function (t) { return acceptLinearText(t); });
|
|
474
|
+
if (!text) {
|
|
475
|
+
text = claimUnreadText(input.unreadTexts, usedTexts, mid, Math.max(length_4 * 0.75, refSize * 6), length_4, function (t) { return acceptLinearText(t); });
|
|
476
|
+
}
|
|
477
|
+
if (!text)
|
|
478
|
+
return "continue";
|
|
479
|
+
text = reconcileLinearDimText(text, length_4);
|
|
480
|
+
// Inside arrows point apart (away from the span centre); outside arrows
|
|
481
|
+
// point toward each other.
|
|
482
|
+
var arrowsOut = a.direction !== undefined && dot(a.direction, u) > 0;
|
|
483
|
+
var consumed = __spreadArray(__spreadArray(__spreadArray([], __read(a.ids), false), __read(b.ids), false), __read(pdfDimTextIds(text)), false);
|
|
484
|
+
try {
|
|
485
|
+
// Dimension line pieces: collinear segments overlapping the span.
|
|
486
|
+
for (var _6 = (e_13 = void 0, __values(input.segments)), _7 = _6.next(); !_7.done; _7 = _6.next()) {
|
|
487
|
+
var s = _7.value;
|
|
488
|
+
if (usedSegments.has(s.id) || consumed.includes(s.id))
|
|
489
|
+
continue;
|
|
490
|
+
var r0 = sub(s.p0, a.tip);
|
|
491
|
+
var r1 = sub(s.p1, a.tip);
|
|
492
|
+
if (Math.abs(dot(r0, n)) > tol * 2 || Math.abs(dot(r1, n)) > tol * 2)
|
|
493
|
+
continue;
|
|
494
|
+
var lo = Math.min(dot(r0, u), dot(r1, u));
|
|
495
|
+
var hi = Math.max(dot(r0, u), dot(r1, u));
|
|
496
|
+
// Overlap the span, or sit entirely in the arrow tails (outside
|
|
497
|
+
// arrows); merely touching a tip is a neighbouring dimension.
|
|
498
|
+
var overlap = Math.min(hi, length_4) - Math.max(lo, 0);
|
|
499
|
+
var inTails = lo >= -refSize * 4 && hi <= length_4 + refSize * 4;
|
|
500
|
+
if (overlap <= tol * 4 && !inTails)
|
|
501
|
+
continue;
|
|
502
|
+
consumed.push(s.id);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
catch (e_13_1) { e_13 = { error: e_13_1 }; }
|
|
506
|
+
finally {
|
|
507
|
+
try {
|
|
508
|
+
if (_7 && !_7.done && (_3 = _6.return)) _3.call(_6);
|
|
509
|
+
}
|
|
510
|
+
finally { if (e_13) throw e_13.error; }
|
|
511
|
+
}
|
|
512
|
+
// Extension lines: perpendicular segments through each tip.
|
|
513
|
+
// Rank 0: tip-near stubs with real object reach (full PDF extension length).
|
|
514
|
+
// Rank 1: mid-crossing edges — keep the text-side endpoint (object side).
|
|
515
|
+
// Rank 2: tiny tip-only stubs (DIMEXE overhang) — last resort only.
|
|
516
|
+
// Never let a 1-unit beyond stub beat a 40-unit object-side edge.
|
|
517
|
+
var beyond = 0;
|
|
518
|
+
var maxTipGap = Math.max(refSize * 2, a.size * 2, text.height * 1.5);
|
|
519
|
+
var minReach = Math.max(a.size * 2, text.height, refSize * 2);
|
|
520
|
+
var textSide = Math.sign((text.center.x - mid.x) * n.x + (text.center.y - mid.y) * n.y) || 1;
|
|
521
|
+
var extension = function (tip) {
|
|
522
|
+
var e_16, _a;
|
|
523
|
+
var best;
|
|
524
|
+
try {
|
|
525
|
+
for (var _b = (e_16 = void 0, __values(input.segments)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
526
|
+
var s = _c.value;
|
|
527
|
+
var shared = extensionIds.has(s.id);
|
|
528
|
+
if ((usedSegments.has(s.id) && !shared) || consumed.includes(s.id)) {
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
var su = unit(sub(s.p1, s.p0));
|
|
532
|
+
if (Math.abs(dot(su, u)) > sinTol)
|
|
533
|
+
continue;
|
|
534
|
+
if (Math.abs(cross(su, sub(tip, s.p0))) > tol * 2)
|
|
535
|
+
continue;
|
|
536
|
+
var t0 = dot(sub(s.p0, tip), n);
|
|
537
|
+
var t1 = dot(sub(s.p1, tip), n);
|
|
538
|
+
// The tip must lie on (or just past) the segment.
|
|
539
|
+
if (Math.min(t0, t1) > tol * 2 || Math.max(t0, t1) < -tol * 2) {
|
|
540
|
+
if (Math.min(Math.abs(t0), Math.abs(t1)) > maxTipGap)
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
var d0 = Math.abs(t0);
|
|
544
|
+
var d1 = Math.abs(t1);
|
|
545
|
+
var tipNear0 = d0 <= maxTipGap;
|
|
546
|
+
var tipNear1 = d1 <= maxTipGap;
|
|
547
|
+
var origin_1 = void 0;
|
|
548
|
+
var nearT = void 0;
|
|
549
|
+
var farT = void 0;
|
|
550
|
+
var proximity = void 0;
|
|
551
|
+
var rank = void 0;
|
|
552
|
+
if (tipNear0 || tipNear1) {
|
|
553
|
+
// Tip near an end → that end is the dim-line foot; other end is origin.
|
|
554
|
+
var nearIs0 = tipNear0 && (!tipNear1 || d0 <= d1);
|
|
555
|
+
nearT = nearIs0 ? t0 : t1;
|
|
556
|
+
farT = nearIs0 ? t1 : t0;
|
|
557
|
+
origin_1 = nearIs0 ? s.p1 : s.p0;
|
|
558
|
+
proximity = Math.abs(nearT);
|
|
559
|
+
// Tiny tip stubs are overhang only; real extensions reach the object.
|
|
560
|
+
rank = Math.abs(farT) >= minReach ? 0 : 2;
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
// Mid-segment long edge: keep the text-side endpoint (object side).
|
|
564
|
+
var on0 = Math.sign(t0) === textSide;
|
|
565
|
+
var on1 = Math.sign(t1) === textSide;
|
|
566
|
+
if (!on0 && !on1)
|
|
567
|
+
continue;
|
|
568
|
+
var use0 = on0 && (!on1 || d0 >= d1);
|
|
569
|
+
origin_1 = use0 ? s.p0 : s.p1;
|
|
570
|
+
farT = use0 ? t0 : t1;
|
|
571
|
+
nearT = use0 ? t1 : t0;
|
|
572
|
+
proximity = Math.abs(nearT);
|
|
573
|
+
rank = 1;
|
|
574
|
+
}
|
|
575
|
+
var reach = Math.abs(farT);
|
|
576
|
+
if (!(reach > tol))
|
|
577
|
+
continue;
|
|
578
|
+
var over = Math.sign(nearT) !== Math.sign(farT) && Math.sign(nearT) !== 0
|
|
579
|
+
? Math.min(Math.abs(nearT), maxTipGap)
|
|
580
|
+
: 0;
|
|
581
|
+
// Prefer better rank, then longer object reach (match PDF length).
|
|
582
|
+
if (!best ||
|
|
583
|
+
rank < best.rank ||
|
|
584
|
+
(rank === best.rank && reach > best.reach + tol) ||
|
|
585
|
+
(rank === best.rank &&
|
|
586
|
+
Math.abs(reach - best.reach) <= tol &&
|
|
587
|
+
proximity < best.proximity)) {
|
|
588
|
+
best = { origin: origin_1, id: s.id, beyond: over, proximity: proximity, reach: reach, rank: rank };
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
catch (e_16_1) { e_16 = { error: e_16_1 }; }
|
|
593
|
+
finally {
|
|
594
|
+
try {
|
|
595
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
596
|
+
}
|
|
597
|
+
finally { if (e_16) throw e_16.error; }
|
|
598
|
+
}
|
|
599
|
+
if (!best)
|
|
600
|
+
return tip;
|
|
601
|
+
if (!extensionIds.has(best.id))
|
|
602
|
+
consumed.push(best.id);
|
|
603
|
+
extensionIds.add(best.id);
|
|
604
|
+
beyond = Math.max(beyond, best.beyond);
|
|
605
|
+
return best.origin;
|
|
606
|
+
};
|
|
607
|
+
var xLine1 = extension(a.tip);
|
|
608
|
+
var xLine2 = extension(b.tip);
|
|
609
|
+
usedArrows.add(a);
|
|
610
|
+
usedArrows.add(b);
|
|
611
|
+
try {
|
|
612
|
+
for (var _8 = (e_14 = void 0, __values(pdfDimTextIds(text))), _9 = _8.next(); !_9.done; _9 = _8.next()) {
|
|
613
|
+
var id = _9.value;
|
|
614
|
+
usedTexts.add(id);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
catch (e_14_1) { e_14 = { error: e_14_1 }; }
|
|
618
|
+
finally {
|
|
619
|
+
try {
|
|
620
|
+
if (_9 && !_9.done && (_4 = _8.return)) _4.call(_8);
|
|
621
|
+
}
|
|
622
|
+
finally { if (e_14) throw e_14.error; }
|
|
623
|
+
}
|
|
624
|
+
try {
|
|
625
|
+
for (var consumed_2 = (e_15 = void 0, __values(consumed)), consumed_2_1 = consumed_2.next(); !consumed_2_1.done; consumed_2_1 = consumed_2.next()) {
|
|
626
|
+
var id = consumed_2_1.value;
|
|
627
|
+
usedSegments.add(id);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
catch (e_15_1) { e_15 = { error: e_15_1 }; }
|
|
631
|
+
finally {
|
|
632
|
+
try {
|
|
633
|
+
if (consumed_2_1 && !consumed_2_1.done && (_5 = consumed_2.return)) _5.call(consumed_2);
|
|
634
|
+
}
|
|
635
|
+
finally { if (e_15) throw e_15.error; }
|
|
636
|
+
}
|
|
637
|
+
var rotation = Math.atan2(u.y, u.x);
|
|
638
|
+
if (rotation < 0)
|
|
639
|
+
rotation += Math.PI;
|
|
640
|
+
if (rotation >= Math.PI - 1e-12)
|
|
641
|
+
rotation -= Math.PI;
|
|
642
|
+
results.push({
|
|
643
|
+
kind: 'linear',
|
|
644
|
+
xLine1: xLine1,
|
|
645
|
+
xLine2: xLine2,
|
|
646
|
+
dimLinePoint: a.tip,
|
|
647
|
+
rotation: rotation,
|
|
648
|
+
measured: length_4,
|
|
649
|
+
text: text,
|
|
650
|
+
arrowSize: a.size,
|
|
651
|
+
extensionBeyond: beyond,
|
|
652
|
+
ticks: a.direction === undefined,
|
|
653
|
+
arrowsOut: arrowsOut,
|
|
654
|
+
consumed: consumed
|
|
655
|
+
});
|
|
656
|
+
};
|
|
657
|
+
try {
|
|
658
|
+
for (var pairs_1 = __values(pairs), pairs_1_1 = pairs_1.next(); !pairs_1_1.done; pairs_1_1 = pairs_1.next()) {
|
|
659
|
+
var _r = pairs_1_1.value, a = _r.a, b = _r.b, length_4 = _r.length;
|
|
660
|
+
_loop_3(a, b, length_4);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
664
|
+
finally {
|
|
665
|
+
try {
|
|
666
|
+
if (pairs_1_1 && !pairs_1_1.done && (_f = pairs_1.return)) _f.call(pairs_1);
|
|
667
|
+
}
|
|
668
|
+
finally { if (e_6) throw e_6.error; }
|
|
669
|
+
}
|
|
670
|
+
results.push.apply(results, __spreadArray([], __read(recognizeBareLinear(input, usedSegments, usedTexts, refSize, tol, sinTol)), false));
|
|
671
|
+
return results;
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Linear dimensions drawn without arrowheads or ticks: a dimension line
|
|
675
|
+
* whose two ends lie inside parallel perpendicular extension lines (which
|
|
676
|
+
* run past it, as DIMEXE does), with a value text beside it. Requiring the
|
|
677
|
+
* extension lines to continue past the dimension line keeps rectangle
|
|
678
|
+
* sides, whose corners are segment ends, from matching.
|
|
679
|
+
*/
|
|
680
|
+
function recognizeBareLinear(input, usedSegments, usedTexts, refSize, tol, sinTol) {
|
|
681
|
+
var e_17, _a;
|
|
682
|
+
var results = [];
|
|
683
|
+
var lines = input.segments
|
|
684
|
+
.map(function (s) { return ({ s: s, length: dist(s.p0, s.p1) }); })
|
|
685
|
+
.filter(function (_a) {
|
|
686
|
+
var length = _a.length;
|
|
687
|
+
return length > tol * 4;
|
|
688
|
+
})
|
|
689
|
+
.sort(function (p, q) { return p.length - q.length; });
|
|
690
|
+
var _loop_4 = function (line, length_5) {
|
|
691
|
+
var e_18, _c, e_19, _d;
|
|
692
|
+
if (usedSegments.has(line.id))
|
|
693
|
+
return "continue";
|
|
694
|
+
var u = unit(sub(line.p1, line.p0));
|
|
695
|
+
var n = { x: -u.y, y: u.x };
|
|
696
|
+
var extensionAt = function (end) {
|
|
697
|
+
var e_20, _a;
|
|
698
|
+
try {
|
|
699
|
+
for (var _b = (e_20 = void 0, __values(input.segments)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
700
|
+
var s = _c.value;
|
|
701
|
+
if (s === line || usedSegments.has(s.id))
|
|
702
|
+
continue;
|
|
703
|
+
var su = unit(sub(s.p1, s.p0));
|
|
704
|
+
if (Math.abs(dot(su, u)) > sinTol)
|
|
705
|
+
continue;
|
|
706
|
+
if (Math.abs(cross(su, sub(end, s.p0))) > tol * 2)
|
|
707
|
+
continue;
|
|
708
|
+
var t0 = dot(sub(s.p0, end), n);
|
|
709
|
+
var t1 = dot(sub(s.p1, end), n);
|
|
710
|
+
// Both sides of the end must be covered: the extension runs past.
|
|
711
|
+
if (Math.min(t0, t1) >= -tol * 2 || Math.max(t0, t1) <= tol * 2) {
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
var farIsP0 = Math.abs(t0) >= Math.abs(t1);
|
|
715
|
+
return {
|
|
716
|
+
id: s.id,
|
|
717
|
+
origin: farIsP0 ? s.p0 : s.p1,
|
|
718
|
+
side: Math.sign(farIsP0 ? t0 : t1),
|
|
719
|
+
beyond: Math.abs(farIsP0 ? t1 : t0)
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
catch (e_20_1) { e_20 = { error: e_20_1 }; }
|
|
724
|
+
finally {
|
|
725
|
+
try {
|
|
726
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
727
|
+
}
|
|
728
|
+
finally { if (e_20) throw e_20.error; }
|
|
729
|
+
}
|
|
730
|
+
return undefined;
|
|
731
|
+
};
|
|
732
|
+
var e1 = extensionAt(line.p0);
|
|
733
|
+
var e2 = extensionAt(line.p1);
|
|
734
|
+
if (!e1 || !e2 || e1.id === e2.id)
|
|
735
|
+
return "continue";
|
|
736
|
+
var mid = lerp(line.p0, line.p1, 0.5);
|
|
737
|
+
var acceptBareText = function (t) {
|
|
738
|
+
if (t.text !== undefined &&
|
|
739
|
+
parsePdfDimensionValue(t.text) === undefined) {
|
|
740
|
+
return false;
|
|
741
|
+
}
|
|
742
|
+
var rel = sub(t.center, line.p0);
|
|
743
|
+
var along = dot(rel, u);
|
|
744
|
+
return (Math.abs(dot(rel, n)) <= t.height * 2.5 &&
|
|
745
|
+
along >= -t.height * 4 &&
|
|
746
|
+
along <= length_5 + t.height * 4);
|
|
747
|
+
};
|
|
748
|
+
var text = nearestText(input.texts, usedTexts, mid, Math.max(length_5 * 0.75, refSize * 6), function (t) { return acceptBareText(t); });
|
|
749
|
+
if (!text) {
|
|
750
|
+
text = claimUnreadText(input.unreadTexts, usedTexts, mid, Math.max(length_5 * 0.75, refSize * 6), length_5, function (t) { return acceptBareText(t); });
|
|
751
|
+
}
|
|
752
|
+
if (!text)
|
|
753
|
+
return "continue";
|
|
754
|
+
try {
|
|
755
|
+
for (var _e = (e_18 = void 0, __values(pdfDimTextIds(text))), _f = _e.next(); !_f.done; _f = _e.next()) {
|
|
756
|
+
var id = _f.value;
|
|
757
|
+
usedTexts.add(id);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
catch (e_18_1) { e_18 = { error: e_18_1 }; }
|
|
761
|
+
finally {
|
|
762
|
+
try {
|
|
763
|
+
if (_f && !_f.done && (_c = _e.return)) _c.call(_e);
|
|
764
|
+
}
|
|
765
|
+
finally { if (e_18) throw e_18.error; }
|
|
766
|
+
}
|
|
767
|
+
var consumed = __spreadArray([line.id, e1.id, e2.id], __read(pdfDimTextIds(text)), false);
|
|
768
|
+
try {
|
|
769
|
+
for (var consumed_3 = (e_19 = void 0, __values(consumed)), consumed_3_1 = consumed_3.next(); !consumed_3_1.done; consumed_3_1 = consumed_3.next()) {
|
|
770
|
+
var id = consumed_3_1.value;
|
|
771
|
+
usedSegments.add(id);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
catch (e_19_1) { e_19 = { error: e_19_1 }; }
|
|
775
|
+
finally {
|
|
776
|
+
try {
|
|
777
|
+
if (consumed_3_1 && !consumed_3_1.done && (_d = consumed_3.return)) _d.call(consumed_3);
|
|
778
|
+
}
|
|
779
|
+
finally { if (e_19) throw e_19.error; }
|
|
780
|
+
}
|
|
781
|
+
var rotation = Math.atan2(u.y, u.x);
|
|
782
|
+
if (rotation < 0)
|
|
783
|
+
rotation += Math.PI;
|
|
784
|
+
if (rotation >= Math.PI - 1e-12)
|
|
785
|
+
rotation -= Math.PI;
|
|
786
|
+
// The object lies on the far side of the extension lines; when they
|
|
787
|
+
// disagree, keep the dimension line ends as origins.
|
|
788
|
+
var sameSide = e1.side === e2.side;
|
|
789
|
+
results.push({
|
|
790
|
+
kind: 'linear',
|
|
791
|
+
xLine1: sameSide ? e1.origin : line.p0,
|
|
792
|
+
xLine2: sameSide ? e2.origin : line.p1,
|
|
793
|
+
dimLinePoint: line.p0,
|
|
794
|
+
rotation: rotation,
|
|
795
|
+
measured: length_5,
|
|
796
|
+
text: reconcileLinearDimText(text, length_5),
|
|
797
|
+
arrowSize: 0,
|
|
798
|
+
extensionBeyond: sameSide ? Math.max(e1.beyond, e2.beyond) : 0,
|
|
799
|
+
ticks: false,
|
|
800
|
+
arrowsOut: false,
|
|
801
|
+
consumed: consumed
|
|
802
|
+
});
|
|
803
|
+
};
|
|
804
|
+
try {
|
|
805
|
+
for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
|
|
806
|
+
var _b = lines_1_1.value, line = _b.s, length_5 = _b.length;
|
|
807
|
+
_loop_4(line, length_5);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
catch (e_17_1) { e_17 = { error: e_17_1 }; }
|
|
811
|
+
finally {
|
|
812
|
+
try {
|
|
813
|
+
if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
|
|
814
|
+
}
|
|
815
|
+
finally { if (e_17) throw e_17.error; }
|
|
816
|
+
}
|
|
817
|
+
return results;
|
|
818
|
+
}
|
|
819
|
+
function pointNearSegment(p, s, tol) {
|
|
820
|
+
var d = sub(s.p1, s.p0);
|
|
821
|
+
var len2 = dot(d, d);
|
|
822
|
+
if (len2 === 0)
|
|
823
|
+
return dist(p, s.p0) <= tol;
|
|
824
|
+
var t = Math.max(0, Math.min(1, dot(sub(p, s.p0), d) / len2));
|
|
825
|
+
return dist(p, lerp(s.p0, s.p1, t)) <= tol;
|
|
826
|
+
}
|
|
827
|
+
function nearestText(texts, used, near, maxDistance, accept) {
|
|
828
|
+
var e_21, _a;
|
|
829
|
+
var best;
|
|
830
|
+
var bestDistance = maxDistance;
|
|
831
|
+
try {
|
|
832
|
+
for (var texts_1 = __values(texts), texts_1_1 = texts_1.next(); !texts_1_1.done; texts_1_1 = texts_1.next()) {
|
|
833
|
+
var text = texts_1_1.value;
|
|
834
|
+
if (used.has(text.id) || !accept(text))
|
|
835
|
+
continue;
|
|
836
|
+
var d = dist(text.center, near);
|
|
837
|
+
if (d <= bestDistance) {
|
|
838
|
+
bestDistance = d;
|
|
839
|
+
best = text;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
catch (e_21_1) { e_21 = { error: e_21_1 }; }
|
|
844
|
+
finally {
|
|
845
|
+
try {
|
|
846
|
+
if (texts_1_1 && !texts_1_1.done && (_a = texts_1.return)) _a.call(texts_1);
|
|
847
|
+
}
|
|
848
|
+
finally { if (e_21) throw e_21.error; }
|
|
849
|
+
}
|
|
850
|
+
return best;
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Claims the nearest unread stroke-text cluster and turns it into a
|
|
854
|
+
* dimension text whose value is the measured length (paper 1:1 fallback
|
|
855
|
+
* when OCR / the glyph dictionary could not read the strokes).
|
|
856
|
+
*/
|
|
857
|
+
function claimUnreadText(unread, used, near, maxDistance, measured, accept) {
|
|
858
|
+
var e_22, _a, e_23, _b;
|
|
859
|
+
if (!unread || unread.length === 0)
|
|
860
|
+
return undefined;
|
|
861
|
+
var best;
|
|
862
|
+
var bestDistance = maxDistance;
|
|
863
|
+
try {
|
|
864
|
+
for (var unread_1 = __values(unread), unread_1_1 = unread_1.next(); !unread_1_1.done; unread_1_1 = unread_1.next()) {
|
|
865
|
+
var text = unread_1_1.value;
|
|
866
|
+
if (used.has(text.id) || !accept(text))
|
|
867
|
+
continue;
|
|
868
|
+
var d = dist(text.center, near);
|
|
869
|
+
if (d <= bestDistance) {
|
|
870
|
+
bestDistance = d;
|
|
871
|
+
best = text;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
catch (e_22_1) { e_22 = { error: e_22_1 }; }
|
|
876
|
+
finally {
|
|
877
|
+
try {
|
|
878
|
+
if (unread_1_1 && !unread_1_1.done && (_a = unread_1.return)) _a.call(unread_1);
|
|
879
|
+
}
|
|
880
|
+
finally { if (e_22) throw e_22.error; }
|
|
881
|
+
}
|
|
882
|
+
if (!best)
|
|
883
|
+
return undefined;
|
|
884
|
+
used.add(best.id);
|
|
885
|
+
try {
|
|
886
|
+
for (var _c = __values(best.extraIds), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
887
|
+
var id = _d.value;
|
|
888
|
+
used.add(id);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
catch (e_23_1) { e_23 = { error: e_23_1 }; }
|
|
892
|
+
finally {
|
|
893
|
+
try {
|
|
894
|
+
if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
|
|
895
|
+
}
|
|
896
|
+
finally { if (e_23) throw e_23.error; }
|
|
897
|
+
}
|
|
898
|
+
return {
|
|
899
|
+
id: best.id,
|
|
900
|
+
text: formatMeasuredLength(measured),
|
|
901
|
+
center: best.center,
|
|
902
|
+
height: best.height,
|
|
903
|
+
extraIds: best.extraIds
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
/** Entity ids that a dimension value text replaces. */
|
|
907
|
+
export function pdfDimTextIds(text) {
|
|
908
|
+
return text.extraIds && text.extraIds.length > 0
|
|
909
|
+
? __spreadArray([text.id], __read(text.extraIds), false) : [text.id];
|
|
910
|
+
}
|
|
911
|
+
/** Compact decimal for a measured length used as a stroke-text fallback. */
|
|
912
|
+
function formatMeasuredLength(length) {
|
|
913
|
+
if (!Number.isFinite(length) || length <= 0)
|
|
914
|
+
return '0';
|
|
915
|
+
var rounded = Math.round(length);
|
|
916
|
+
if (Math.abs(length - rounded) <= Math.max(length * 1e-6, 1e-6)) {
|
|
917
|
+
return String(rounded);
|
|
918
|
+
}
|
|
919
|
+
var text = length.toFixed(4).replace(/\.?0+$/, '');
|
|
920
|
+
return text.length > 0 ? text : String(length);
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Keeps a stroke-read value only when it agrees with the measured length or
|
|
924
|
+
* a clear drawing scale. Over-segmented outline digits often read as "111"
|
|
925
|
+
* and must not become DIMLFAC = 2.
|
|
926
|
+
*/
|
|
927
|
+
function reconcileLinearDimText(text, measured) {
|
|
928
|
+
if (!(measured > 0))
|
|
929
|
+
return text;
|
|
930
|
+
// Leave annotated values alone (`44mm`, tolerances, …); only rewrite plain
|
|
931
|
+
// numeric / R / Ø / ° readings that look like a bad stroke OCR.
|
|
932
|
+
if (!/^[Øø⌀R]?\s*\d+([.,]\d+)?\s*°?$/i.test(text.text.trim()))
|
|
933
|
+
return text;
|
|
934
|
+
var value = parsePdfDimensionValue(text.text);
|
|
935
|
+
var digits = text.text.replace(/\D/g, '');
|
|
936
|
+
if (value === undefined || (digits.length >= 2 && /^1+$/.test(digits))) {
|
|
937
|
+
return __assign(__assign({}, text), { text: formatMeasuredLength(measured) });
|
|
938
|
+
}
|
|
939
|
+
var ratio = value / measured;
|
|
940
|
+
if (Math.abs(ratio - 1) <= 0.05)
|
|
941
|
+
return text;
|
|
942
|
+
if (isNiceScaleRatio(ratio))
|
|
943
|
+
return text;
|
|
944
|
+
return __assign(__assign({}, text), { text: formatMeasuredLength(measured) });
|
|
945
|
+
}
|
|
946
|
+
/** Whether `ratio` is within 1 % of 1, 2, 2.5 or 5 × 10ⁿ. */
|
|
947
|
+
function isNiceScaleRatio(ratio) {
|
|
948
|
+
var e_24, _a, e_25, _b;
|
|
949
|
+
if (!(ratio > 0))
|
|
950
|
+
return false;
|
|
951
|
+
var exponent = Math.floor(Math.log10(ratio));
|
|
952
|
+
try {
|
|
953
|
+
for (var _c = __values([exponent - 1, exponent, exponent + 1]), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
954
|
+
var e = _d.value;
|
|
955
|
+
try {
|
|
956
|
+
for (var _e = (e_25 = void 0, __values([1, 2, 2.5, 5])), _f = _e.next(); !_f.done; _f = _e.next()) {
|
|
957
|
+
var m = _f.value;
|
|
958
|
+
var nice = m * Math.pow(10, e);
|
|
959
|
+
if (Math.abs(nice - ratio) <= ratio * 0.01)
|
|
960
|
+
return true;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
catch (e_25_1) { e_25 = { error: e_25_1 }; }
|
|
964
|
+
finally {
|
|
965
|
+
try {
|
|
966
|
+
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
|
|
967
|
+
}
|
|
968
|
+
finally { if (e_25) throw e_25.error; }
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
catch (e_24_1) { e_24 = { error: e_24_1 }; }
|
|
973
|
+
finally {
|
|
974
|
+
try {
|
|
975
|
+
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
976
|
+
}
|
|
977
|
+
finally { if (e_24) throw e_24.error; }
|
|
978
|
+
}
|
|
979
|
+
return false;
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Most common text-value / measured-length ratio, i.e. the drawing scale the
|
|
983
|
+
* PDF was printed at. Uses linear dimensions when there are any. Returns `undefined` when
|
|
984
|
+
* no dimension has a numeric text.
|
|
985
|
+
*/
|
|
986
|
+
export function suggestPdfDimensionScale(dimensions) {
|
|
987
|
+
var e_26, _a;
|
|
988
|
+
// Linear dimensions are the reliable signal; radial texts are often
|
|
989
|
+
// annotated independently of the drawing scale.
|
|
990
|
+
var linear = dimensions.filter(function (d) { return d.kind === 'linear'; });
|
|
991
|
+
var radial = dimensions.filter(function (d) { return d.kind === 'radius' || d.kind === 'diameter'; });
|
|
992
|
+
// Angles do not scale with the drawing, so they never vote.
|
|
993
|
+
var ratios = (linear.length > 0 ? linear : radial)
|
|
994
|
+
.map(function (d) {
|
|
995
|
+
var value = parsePdfDimensionValue(d.text.text);
|
|
996
|
+
return value !== undefined && d.measured > 0 ? value / d.measured : NaN;
|
|
997
|
+
})
|
|
998
|
+
.filter(function (r) { return Number.isFinite(r) && r > 0; });
|
|
999
|
+
if (ratios.length === 0)
|
|
1000
|
+
return undefined;
|
|
1001
|
+
// Cluster ratios within 1 % and take the biggest cluster's median.
|
|
1002
|
+
var best = [];
|
|
1003
|
+
var _loop_5 = function (r) {
|
|
1004
|
+
var cluster = ratios.filter(function (x) { return Math.abs(x - r) <= r * 0.01; });
|
|
1005
|
+
if (cluster.length > best.length)
|
|
1006
|
+
best = cluster;
|
|
1007
|
+
};
|
|
1008
|
+
try {
|
|
1009
|
+
for (var ratios_1 = __values(ratios), ratios_1_1 = ratios_1.next(); !ratios_1_1.done; ratios_1_1 = ratios_1.next()) {
|
|
1010
|
+
var r = ratios_1_1.value;
|
|
1011
|
+
_loop_5(r);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
catch (e_26_1) { e_26 = { error: e_26_1 }; }
|
|
1015
|
+
finally {
|
|
1016
|
+
try {
|
|
1017
|
+
if (ratios_1_1 && !ratios_1_1.done && (_a = ratios_1.return)) _a.call(ratios_1);
|
|
1018
|
+
}
|
|
1019
|
+
finally { if (e_26) throw e_26.error; }
|
|
1020
|
+
}
|
|
1021
|
+
return median(best);
|
|
1022
|
+
}
|
|
1023
|
+
//# sourceMappingURL=pdfDimensionPattern.js.map
|