@vertigis/arcgis-extensions 51.12.0 → 51.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/data/convert.d.ts +24 -0
  2. package/data/convert.js +1 -1
  3. package/data/support/_dxfConverters.d.ts +538 -0
  4. package/data/support/_dxfConverters.js +1 -0
  5. package/data/support/_dxfFunctions.d.ts +82 -0
  6. package/data/support/_dxfFunctions.js +1 -0
  7. package/data/support/_dxfInterfaces.d.ts +913 -0
  8. package/data/support/_dxfInterfaces.js +1 -0
  9. package/docs/html/assets/navigation.js +1 -1
  10. package/docs/html/assets/search.js +1 -1
  11. package/docs/html/classes/data_support__dxfConverters.DxfEntityProcessor.html +31 -0
  12. package/docs/html/classes/data_support__dxfConverters.DxfToGeoJsonInsertBlockMapper.html +29 -0
  13. package/docs/html/classes/data_support__dxfConverters.DxfToGeoJsonLineMapper.html +12 -0
  14. package/docs/html/classes/data_support__dxfConverters.DxfToGeoJsonPolygonMapper.html +21 -0
  15. package/docs/html/classes/data_support__dxfConverters.DxfToGeoJsonTextMapper.html +28 -0
  16. package/docs/html/functions/data_convert.dxfToLayerExtensions.html +7 -0
  17. package/docs/html/functions/data_support__dxfConverters.mapDXFLineTypeToEsri.html +13 -0
  18. package/docs/html/functions/data_support__dxfFunctions.deriveAnnotationMinScale.html +7 -0
  19. package/docs/html/functions/data_support__dxfFunctions.intToRGB.html +4 -0
  20. package/docs/html/functions/data_support__dxfFunctions.mapBasicLineType.html +5 -0
  21. package/docs/html/functions/data_support__dxfFunctions.mapDXFLineTypeToEsri.html +6 -0
  22. package/docs/html/functions/data_support__dxfFunctions.mapIsoPatterns.html +4 -0
  23. package/docs/html/functions/data_support__dxfFunctions.mapLineTypePattern.html +5 -0
  24. package/docs/html/functions/data_support__dxfFunctions.normalizeFillStyle.html +4 -0
  25. package/docs/html/functions/data_support__dxfFunctions.normalizeLineOutline.html +8 -0
  26. package/docs/html/hierarchy.html +1 -1
  27. package/docs/html/interfaces/data_convert.DxfToLayerExtensionsOptions.html +6 -0
  28. package/docs/html/interfaces/data_support__dxfInterfaces.DxfBlock.html +15 -0
  29. package/docs/html/interfaces/data_support__dxfInterfaces.DxfEntity.html +42 -0
  30. package/docs/html/interfaces/data_support__dxfInterfaces.DxfJsonComponentProperties.html +18 -0
  31. package/docs/html/interfaces/data_support__dxfInterfaces.DxfPoint.html +8 -0
  32. package/docs/html/interfaces/data_support__dxfInterfaces.DxfScale.html +9 -0
  33. package/docs/html/interfaces/data_support__dxfInterfaces.IAttDefEntity.html +22 -0
  34. package/docs/html/interfaces/data_support__dxfInterfaces.IBaseTable.html +6 -0
  35. package/docs/html/interfaces/data_support__dxfInterfaces.IDxfData.html +10 -0
  36. package/docs/html/interfaces/data_support__dxfInterfaces.IDxfJsonComponentContext.html +62 -0
  37. package/docs/html/interfaces/data_support__dxfInterfaces.ILayer.html +12 -0
  38. package/docs/html/interfaces/data_support__dxfInterfaces.ILayerTypesTable.html +8 -0
  39. package/docs/html/interfaces/data_support__dxfInterfaces.ILayersTable.html +8 -0
  40. package/docs/html/interfaces/data_support__dxfInterfaces.ILineEntityExtended.html +4 -0
  41. package/docs/html/interfaces/data_support__dxfInterfaces.ILineType.html +10 -0
  42. package/docs/html/interfaces/data_support__dxfInterfaces.ILwpolylineEntityExtended.html +4 -0
  43. package/docs/html/interfaces/data_support__dxfInterfaces.IMTextEntity.html +18 -0
  44. package/docs/html/interfaces/data_support__dxfInterfaces.IPolylineEntityExtended.html +6 -0
  45. package/docs/html/interfaces/data_support__dxfInterfaces.ITables.html +8 -0
  46. package/docs/html/interfaces/data_support__dxfInterfaces.ITextEntityExtended.html +18 -0
  47. package/docs/html/interfaces/data_support__dxfInterfaces.IViewPort.html +50 -0
  48. package/docs/html/interfaces/data_support__dxfInterfaces.IViewPortTable.html +8 -0
  49. package/docs/html/interfaces/data_support__dxfInterfaces.LineStyle.html +4 -0
  50. package/docs/html/interfaces/data_support__dxfInterfaces.RendererPolygonEntry.html +12 -0
  51. package/docs/html/interfaces/data_support__dxfInterfaces.SimpleFillSymbolJSON.html +12 -0
  52. package/docs/html/interfaces/data_support__dxfInterfaces.SimpleMarkerSymbolDXF.html +10 -0
  53. package/docs/html/interfaces/data_support__dxfInterfaces.TextGraphicAttr.html +15 -0
  54. package/docs/html/modules/data_convert.html +2 -0
  55. package/docs/html/modules/data_support__dxfConverters.html +7 -0
  56. package/docs/html/modules/data_support__dxfFunctions.html +11 -0
  57. package/docs/html/modules/data_support__dxfInterfaces.html +30 -0
  58. package/docs/html/modules.html +3 -0
  59. package/docs/html/types/data_support__dxfFunctions.SimpleFillStyle.html +2 -0
  60. package/docs/html/types/data_support__dxfInterfaces.RendererObjectLine.html +9 -0
  61. package/docs/html/types/data_support__dxfInterfaces.RendererObjectPoint.html +5 -0
  62. package/docs/html/types/data_support__dxfInterfaces.RendererObjectPolygon.html +11 -0
  63. package/docs/html/variables/data_support__dxfFunctions.VALID_FILL_STYLES.html +1 -0
  64. package/docs/html/variables/version.version.html +1 -1
  65. package/package.json +3 -1
  66. package/utilities/_project.js +1 -1
  67. package/version.d.ts +1 -1
  68. package/version.js +1 -1
@@ -0,0 +1,538 @@
1
+ import Point from "@arcgis/core/geometry/Point";
2
+ import type SpatialReference from "@arcgis/core/geometry/SpatialReference";
3
+ import type FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
4
+ import GeoJSONLayer from "@arcgis/core/layers/GeoJSONLayer";
5
+ import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer";
6
+ import type { IArcEntity, ICircleEntity, IEntity, IInsertEntity, IPointEntity, ISolidEntity, ILineType } from "dxf-parser";
7
+ import type { IDxfJsonComponentContext, ILineEntityExtended, IPolylineEntityExtended, ILwpolylineEntityExtended, ITextEntityExtended, IMTextEntity, IAttDefEntity } from "./_dxfInterfaces.js";
8
+ /**
9
+ * Handles DXF LINE, ARC, POLYLINE, and LWPOLYLINE entity parsing and converts
10
+ * them into corresponding GeoJSON line features.
11
+ */
12
+ export declare class DxfToGeoJsonLineMapper {
13
+ dxfContext: IDxfJsonComponentContext;
14
+ constructor(dxfContext: IDxfJsonComponentContext);
15
+ processLine(entity: ILineEntityExtended): Promise<void>;
16
+ processPolyline(entity: IPolylineEntityExtended): Promise<void>;
17
+ processLWPolyline(entity: ILwpolylineEntityExtended): Promise<void>;
18
+ processArc(entity: IArcEntity): Promise<void>;
19
+ /**
20
+ * Converts parsed DXF line features into a GeoJSONLayer and appends it to
21
+ * the dxfContext collection.
22
+ */
23
+ lineToGeoJSON(): void;
24
+ /**
25
+ * Determines the appropriate RGBA color for a given DXF entity.
26
+ *
27
+ * This method prioritizes the provided color value, but falls back to a
28
+ * default symbol color if the input color is undefined. It handles various
29
+ * color formats including DXF integer codes, RGBA arrays, and Esri Color
30
+ * objects.
31
+ *
32
+ * @private
33
+ * @param entity The DXF entity for which to determine the color.
34
+ * @param color The color value from the entity or its layer, which can be a
35
+ * number, number array, or Color object.
36
+ * @returns An RGBA color array (e.g., `[255, 0, 0, 1]`).
37
+ */
38
+ private _getLayerColor;
39
+ /**
40
+ * Interpolates an arc segment defined by two points and a bulge value into
41
+ * a series of straight line segments.
42
+ *
43
+ * The bulge is the tangent of one-fourth of the included angle of the arc.
44
+ * A positive bulge indicates a counter-clockwise arc from the start point
45
+ * to the end point. A negative bulge indicates a clockwise arc.
46
+ *
47
+ * @private
48
+ * @param p1 The starting point of the arc segment.
49
+ * @param p2 The ending point of the arc segment.
50
+ * @param bulge The bulge value defining the arc's curvature.
51
+ * @param segments The number of segments to use for interpolation. Defaults
52
+ * to 16.
53
+ * @returns An array of coordinate pairs `[x, y]` representing the
54
+ * interpolated points along the arc, excluding the start point.
55
+ */
56
+ private _interpolateBulge;
57
+ /**
58
+ * Builds a series of interpolated points from a lightweight polyline
59
+ * (LWPOLYLINE) entity, handling both straight segments and arc segments
60
+ * defined by bulge values.
61
+ *
62
+ * @private
63
+ * @param entity The LWPOLYLINE entity to process.
64
+ * @returns An array of `DxfPoint` objects representing the vertices of the
65
+ * interpolated polyline.
66
+ */
67
+ private _buildBulgeInterpolatedPoints;
68
+ /**
69
+ * Builds a GeoJSON feature for a lightweight polyline (LWPOLYLINE) entity.
70
+ *
71
+ * This method creates either a `Polygon` or a `LineString` geometry based
72
+ * on whether the polyline is closed. The resulting feature includes all
73
+ * original entity properties, plus the resolved color.
74
+ *
75
+ * @private
76
+ * @param entity The extended lightweight polyline entity.
77
+ * @param coords The array of coordinates for the polyline.
78
+ * @param closed A boolean indicating if the polyline is closed.
79
+ * @param color The color to be associated with the feature.
80
+ * @returns A GeoJSON feature object.
81
+ */
82
+ private _buildLWPolylineFeature;
83
+ /**
84
+ * Extracts and projects the coordinates of a POLYLINE entity.
85
+ *
86
+ * @private
87
+ * @param entity The polyline entity to process.
88
+ * @returns A promise that resolves to an array of projected coordinate
89
+ * pairs.
90
+ */
91
+ private _getPolylineCoordinates;
92
+ /**
93
+ * Ensures that a coordinate array represents a closed ring by adding the
94
+ * start point to the end if it's not already closed.
95
+ *
96
+ * @private
97
+ * @param coords The array of coordinate pairs to check and close.
98
+ */
99
+ private _ensureClosed;
100
+ /**
101
+ * Builds a GeoJSON feature from a POLYLINE entity.
102
+ *
103
+ * @private
104
+ * @param entity The extended polyline entity.
105
+ * @param coords The array of coordinates for the polyline.
106
+ * @param closed A boolean indicating if the polyline is closed, which
107
+ * determines if the output is a Polygon or LineString.
108
+ * @param color The optional color to be associated with the feature.
109
+ * @returns A GeoJSON feature object.
110
+ */
111
+ private _buildPolylineFeature;
112
+ /**
113
+ * Adds a polygon feature to the context and configures its renderer symbol.
114
+ *
115
+ * @private
116
+ * @param entity The polyline entity that forms the polygon.
117
+ * @param layerColor The color to apply to the polygon's fill and outline.
118
+ * @param feature The GeoJSON feature to be added.
119
+ */
120
+ private _applyPolygonRenderer;
121
+ /**
122
+ * Adds a line feature to the context and configures its renderer symbol.
123
+ *
124
+ * @private
125
+ * @param entity The polyline entity that forms the line.
126
+ * @param feature The GeoJSON feature to be added.
127
+ */
128
+ private _applyLineRenderer;
129
+ /**
130
+ * Checks if two points are approximately at the same location within a
131
+ * given tolerance.
132
+ *
133
+ * @private
134
+ * @param p1 The first point as a `[number, number]` tuple.
135
+ * @param p2 The second point as a `[number, number]` tuple.
136
+ * @param tol The tolerance for the comparison. Defaults to 1e-6.
137
+ * @returns `true` if the points are within the tolerance, otherwise
138
+ * `false`.
139
+ */
140
+ private _isSamePoint;
141
+ /**
142
+ * Merges consecutive line and arc features that are connected end-to-end
143
+ * and belong to the same layer.
144
+ *
145
+ * @private
146
+ * @param lineFeatures An array of GeoJSON line features to process.
147
+ * @returns A new array of features with connected segments merged into
148
+ * single `LineString` features.
149
+ */
150
+ private _mergeConnectedLinesAndArcs;
151
+ }
152
+ /**
153
+ * The DxfToGeoJsonPolygonMapper class processes DXF polygon-based entities such
154
+ * as SOLID and CIRCLE, converting them into GeoJSON features. It also builds
155
+ * corresponding renderers and sublayers for visualization.
156
+ */
157
+ export declare class DxfToGeoJsonPolygonMapper {
158
+ /**
159
+ * The shared DXF context containing references to dxfContext, renderers,
160
+ * and layers.
161
+ */
162
+ dxfContext: IDxfJsonComponentContext;
163
+ /**
164
+ * Creates a new instance of the DxfToGeoJsonPolygonMapper class.
165
+ *
166
+ * @param dxfContext The shared DXF conversion context.
167
+ */
168
+ constructor(dxfContext: IDxfJsonComponentContext);
169
+ /**
170
+ * Processes a DXF SOLID entity, converts it to a polygon feature, and
171
+ * stores it within the context for GeoJSON conversion.
172
+ *
173
+ * @param entity The DXF SOLID entity to process.
174
+ */
175
+ processSolid(entity: ISolidEntity): Promise<void>;
176
+ /**
177
+ * Processes a DXF CIRCLE entity and converts it into an approximate polygon
178
+ * (ring) for GeoJSON representation.
179
+ *
180
+ * @param entity The DXF CIRCLE entity to process.
181
+ */
182
+ processCircle(entity: ICircleEntity): Promise<void>;
183
+ /**
184
+ * Converts all processed polygon features into a GeoJSONLayer and adds it
185
+ * to the dxfContext collection.
186
+ */
187
+ polygonToGeoJSON(): void;
188
+ }
189
+ /**
190
+ * The DxfToGeoJsonTextMapper class processes DXF text-related entities (TEXT,
191
+ * MTEXT, ATTDEF) and converts them into corresponding GeoJSON or graphics
192
+ * layers. It manages text content, rotation, positioning, and labeling
193
+ * details.
194
+ */
195
+ export declare class DxfToGeoJsonTextMapper {
196
+ /**
197
+ * Shared DXF context containing references to renderer objects, spatial
198
+ * references, and feature collections.
199
+ */
200
+ dxfContext: IDxfJsonComponentContext;
201
+ /**
202
+ * Initializes a new instance of the DxfToGeoJsonTextMapper.
203
+ *
204
+ * @param dxfContext The shared DXF conversion context.
205
+ */
206
+ constructor(dxfContext: IDxfJsonComponentContext);
207
+ /**
208
+ * Processes a DXF TEXT entity and converts it into a GeoJSON point feature
209
+ * with text attributes such as rotation and height.
210
+ *
211
+ * @param entity The DXF TEXT entity to process.
212
+ */
213
+ processText(entity: ITextEntityExtended): Promise<void>;
214
+ /**
215
+ * Processes a DXF MTEXT entity (multi-line text) and converts it into a
216
+ * cleaned and formatted GeoJSON point feature.
217
+ *
218
+ * @param entity The DXF MTEXT entity to process.
219
+ */
220
+ processMText(entity: IMTextEntity): Promise<void>;
221
+ /**
222
+ * Processes a DXF ATTDEF (attribute definition) entity and converts it into
223
+ * a text-based GeoJSON point feature with block, tag, and rotation
224
+ * properties.
225
+ *
226
+ * @param entity The DXF ATTDEF entity to process.
227
+ */
228
+ processAttDef(entity: IAttDefEntity): Promise<void>;
229
+ /**
230
+ * Converts all processed text features (TEXT, MTEXT, ATTDEF) into a
231
+ * GraphicsLayer for map annotation visualization.
232
+ */
233
+ AnnotationToGeoJSON(): void;
234
+ getMaximumFontSize(graphics: (__esri.Graphic | undefined)[]): number;
235
+ /**
236
+ * Creates a graphic representation for a DXF text-based feature.
237
+ *
238
+ * @private
239
+ * @param feature The GeoJSON feature representing the text entity.
240
+ * @param placementMap A map from DXF attachment points to ArcGIS label
241
+ * placements.
242
+ * @param hAlignMap A map for horizontal alignment.
243
+ * @param vAlignMap A map for vertical alignment.
244
+ * @returns A new `Graphic` object or `null` if the feature cannot be
245
+ * processed.
246
+ */
247
+ private _createTextGraphic;
248
+ /**
249
+ * Extracts and cleans the text string from various potential properties of
250
+ * a DXF entity.
251
+ *
252
+ * @private
253
+ * @param props The properties object from a GeoJSON feature.
254
+ * @returns The extracted and trimmed text string, or an empty string if no
255
+ * text is found.
256
+ */
257
+ private _getTextString;
258
+ /**
259
+ * Determines the color for a text entity based on its properties or layer
260
+ * settings.
261
+ *
262
+ * @private
263
+ * @param props The properties object from a GeoJSON feature.
264
+ * @returns An RGBA color array.
265
+ */
266
+ private _getTextColor;
267
+ /**
268
+ * Calculates the font size for a text entity from its height property.
269
+ *
270
+ * @private
271
+ * @param props The properties object from a GeoJSON feature.
272
+ * @returns The calculated font size.
273
+ */
274
+ private _getFontSize;
275
+ /**
276
+ * Determines the rotation angle for a text entity.
277
+ *
278
+ * @private
279
+ * @param props The properties object from a GeoJSON feature.
280
+ * @returns The rotation angle in degrees.
281
+ */
282
+ private _getRotation;
283
+ /**
284
+ * Extracts the x and y offsets from the entity's scale properties.
285
+ *
286
+ * @private
287
+ * @param props The properties object from a GeoJSON feature.
288
+ * @returns An object containing the x and y offsets.
289
+ */
290
+ private _getOffsets;
291
+ /**
292
+ * Determines the label placement and alignment for a text entity.
293
+ *
294
+ * @private
295
+ * @param props The properties object from a GeoJSON feature.
296
+ * @param placementMap A map from DXF attachment points to ArcGIS label
297
+ * placements.
298
+ * @param hAlignMap A map for horizontal alignment.
299
+ * @param vAlignMap A map for vertical alignment.
300
+ * @returns An object with label placement and alignment properties.
301
+ */
302
+ private _getAlignment;
303
+ }
304
+ /**
305
+ * Handles DXF `INSERT` entities (block insertions) and their nested entities.
306
+ * This dxfContext processes inserted blocks, applies transformations (rotation,
307
+ * scale, position), and generates GeoJSON or map layers for point-based block
308
+ * placements.
309
+ */
310
+ export declare class DxfToGeoJsonInsertBlockMapper {
311
+ /**
312
+ * The shared DXF processing context, including renderer objects and feature
313
+ * collections.
314
+ */
315
+ dxfContext: IDxfJsonComponentContext;
316
+ /**
317
+ * Creates a new instance of the DxfToGeoJsonInsertBlockMapper.
318
+ *
319
+ * @param dxfContext The shared DXF conversion context.
320
+ */
321
+ constructor(dxfContext: IDxfJsonComponentContext);
322
+ /**
323
+ * Processes a DXF `INSERT` entity that references a block definition.
324
+ * Applies translation, rotation, and scaling to all entities within the
325
+ * block, creating corresponding GeoJSON point features and rendering
326
+ * symbols.
327
+ *
328
+ * @param insert The DXF insert definition representing the block reference.
329
+ * @returns A Promise that resolves once all block entities are processed.
330
+ */
331
+ processInsertFunction(insert: IInsertEntity): Promise<void>;
332
+ /**
333
+ * Processes a DXF `POINT` entity and creates its corresponding GeoJSON
334
+ * point representation.
335
+ *
336
+ * @param entity The DXF `POINT` entity to process.
337
+ */
338
+ processPoint(entity: IPointEntity): Promise<void>;
339
+ /**
340
+ * Processes a top-level DXF `INSERT` entity and creates its corresponding
341
+ * GeoJSON point representation with block information.
342
+ *
343
+ * @param entity The DXF `INSERT` entity to process.
344
+ */
345
+ processInsert(entity: IInsertEntity): Promise<void>;
346
+ /**
347
+ * Converts all processed point features into a GeoJSONLayer and adds it to
348
+ * the sublayer list for visualization.
349
+ */
350
+ pointToGeoJSON(): void;
351
+ /**
352
+ * Creates and pushes the GeoJSON point feature for the inserted block.
353
+ *
354
+ * @private
355
+ * @param {{ name: string | number; layer: string | number }} insert The DXF
356
+ * insert definition containing name and layer information.
357
+ * @param {DxfBlock | undefined} block The referenced DXF block definition,
358
+ * if available.
359
+ * @param {number} rotation The rotation angle of the block in degrees.
360
+ * @param {number} lon The longitude (X coordinate) of the block in the
361
+ * target spatial reference.
362
+ * @param {number} lat The latitude (Y coordinate) of the block in the
363
+ * target spatial reference.
364
+ * @returns {void}
365
+ */
366
+ private _createInsertPointFeature;
367
+ /**
368
+ * Builds a renderer object (symbol definition) for a given DXF layer.
369
+ *
370
+ * @private
371
+ * @param {string} layerKey The unique identifier or name of the DXF layer.
372
+ * @param {{ layer: string | number }} insert The DXF insert definition used
373
+ * to determine color and style.
374
+ * @returns {RendererObjectPoint[string]} Returns the renderer entry for the
375
+ * specified layer.
376
+ */
377
+ private _createLayerSymbol;
378
+ /**
379
+ * Iterates through all entities within a DXF block and applies geometric
380
+ * transformations (scaling, rotation, and translation) before sending them
381
+ * for DXF entity processing.
382
+ *
383
+ * @private
384
+ * @param {DxfBlock} block The DXF block containing entities to process.
385
+ * @param {{
386
+ * name: string | number;
387
+ * rotation: number;
388
+ * scale: { x: number; y: number; z: number };
389
+ * position: { x: number; y: number };
390
+ * layer: string | number;
391
+ * }} insert
392
+ * The DXF insert context providing block reference, layer, and
393
+ * transformation data.
394
+ * @param {number} rotation The rotation angle in degrees to apply to
395
+ * entities.
396
+ * @param {{ x: number; y: number; z: number }} scale The scaling factors
397
+ * per axis.
398
+ * @param {{ x: number; y: number }} position The insertion position to
399
+ * offset transformed entities.
400
+ * @returns {Promise<void>} Resolves once all entities have been transformed
401
+ * and processed.
402
+ */
403
+ private _normalizeBlockEntities;
404
+ /**
405
+ * Iterates through all entities within a DXF block and applies geometric
406
+ * transformations (scaling, rotation, and translation) before sending them
407
+ * for DXF entity processing.
408
+ *
409
+ * @private
410
+ * @param block The DXF block containing entities to process.
411
+ * @param insert The DXF insert context providing block reference, layer,
412
+ * and transformation data.
413
+ * @param rotation The rotation angle in degrees to apply to entities.
414
+ * @param scale The scaling factors per axis.
415
+ * @param position The insertion position to offset transformed entities.
416
+ * @param position.x The X coordinate of the insertion point.
417
+ * @param position.y The Y coordinate of the insertion point.
418
+ * @returns A promise that resolves once all entities have been transformed
419
+ * and processed.
420
+ */
421
+ private _processBlockEntities;
422
+ /**
423
+ * Applies geometric transformations (scaling, rotation, and translation) to
424
+ * a DXF entity's geometric components.
425
+ *
426
+ * @private
427
+ * @param {DxfEntity} entity The entity to transform.
428
+ * @param {{ x: number; y: number; z: number }} scale Scaling factors along
429
+ * each axis.
430
+ * @param {number} scale.x The scaling factor along the X-axis.
431
+ * @param {number} scale.y The scaling factor along the Y-axis.
432
+ * @param {number} scale.z The scaling factor along the Z-axis.
433
+ * @param {number} rotation The rotation angle in degrees.
434
+ * @param {{ x: number; y: number }} position Translation offset to apply.
435
+ * @param {number} position.x The X coordinate offset.
436
+ * @param {number} position.y The Y coordinate offset.
437
+ * @returns {void}
438
+ */
439
+ private _transformEntityGeometry;
440
+ /**
441
+ * Adjusts non-geometric attributes such as radius, height, and rotation,
442
+ * and assigns the block name after all transformations are applied.
443
+ *
444
+ * @private
445
+ * @param {DxfEntity} entity The DXF entity being modified.
446
+ * @param {{ x: number; y: number; z: number }} scale The scaling factors
447
+ * applied to the entity.
448
+ * @param {number} scale.x The scale factor along the X-axis.
449
+ * @param {number} scale.y The scale factor along the Y-axis.
450
+ * @param {number} scale.z The scale factor along the Z-axis.
451
+ * @param {number} rotation The rotation (in degrees) applied to the entity.
452
+ * @param {string} blockName The name of the parent DXF block.
453
+ * @returns {void} This function modifies the entity in place and does not
454
+ * return a value.
455
+ */
456
+ private _adjustEntityAttributes;
457
+ }
458
+ /**
459
+ * Maps a DXF line type name to an equivalent Esri simple line style.
460
+ *
461
+ * This function attempts to map a DXF line type to a named Esri line style such
462
+ * as "dash" or "dot". The mapping is based on a combination of the line type's
463
+ * name and its pattern definition. It checks for common names (e.g., "HIDDEN",
464
+ * "CENTER"), ISO patterns, and analyzes the dash-gap pattern for a best-fit
465
+ * match.
466
+ *
467
+ * @param lineTypeName The name of the DXF line type (e.g., "DASHED", "ISO dash
468
+ * space").
469
+ * @param lineTypeObj The full DXF line type object, which may contain a
470
+ * `pattern` array of numbers defining dashes and gaps.
471
+ * @returns An Esri simple line style string. If no specific match is found, it
472
+ * defaults to "solid".
473
+ */
474
+ export declare function mapDXFLineTypeToEsri(lineTypeName: string, lineTypeObj: ILineType | undefined): "solid" | "dash" | "dot" | "dash-dot" | "long-dash" | "long-dash-dot" | "short-dash" | "short-dash-dot";
475
+ /**
476
+ * Processes various DXF entities and dispatches them to the appropriate mapper
477
+ * class for conversion to GeoJSON features.
478
+ */
479
+ export declare class DxfEntityProcessor {
480
+ /**
481
+ * The shared DXF conversion context.
482
+ *
483
+ * @private
484
+ */
485
+ private readonly dxfContext;
486
+ /**
487
+ * A map of DXF entity types to their corresponding handler functions.
488
+ *
489
+ * @private
490
+ */
491
+ private readonly entityHandlers;
492
+ /**
493
+ * Initializes a new instance of the DxfEntityProcessor.
494
+ *
495
+ * @param sourceSR The source spatial reference of the DXF data.
496
+ * @param targetSR The target spatial reference for the output layers.
497
+ * @param contextOverrides Optional partial context to override default
498
+ * values.
499
+ */
500
+ constructor(sourceSR: SpatialReference, targetSR: SpatialReference, contextOverrides?: Partial<IDxfJsonComponentContext>);
501
+ /**
502
+ * Returns the fully constructed DXF conversion context.
503
+ *
504
+ * @returns The shared DXF conversion context.
505
+ */
506
+ getContext(): IDxfJsonComponentContext;
507
+ /**
508
+ * Converts a single coordinate pair from the source spatial reference to
509
+ * the target spatial reference.
510
+ *
511
+ * @param x The x-coordinate to convert.
512
+ * @param y The y-coordinate to convert.
513
+ * @returns A promise that resolves with the converted [x, y] coordinates.
514
+ */
515
+ convertToSpatialReference(x: number, y: number): Promise<[number, number]>;
516
+ /**
517
+ * Project an array of points into the target spatial reference.
518
+ *
519
+ * @param points Array of points to project.
520
+ * @returns Array of converted coordinate pairs.
521
+ */
522
+ projectMany(points: Point[]): Promise<[number, number][]>;
523
+ /**
524
+ * Processes a single DXF entity or an array of entities. It filters out
525
+ * "BLOCK" and "ENDBLK" types and dispatches the rest to the appropriate
526
+ * handler.
527
+ *
528
+ * @param entity The entity or array of entities to process.
529
+ */
530
+ process(entity: IEntity | IEntity[]): Promise<void>;
531
+ /**
532
+ * Processes all entities from the DXF data in batches to keep the UI
533
+ * responsive.
534
+ *
535
+ * @returns A promise that resolves with an array of the generated layers.
536
+ */
537
+ processAll(): Promise<(GeoJSONLayer | GraphicsLayer | FeatureLayer)[]>;
538
+ }
@@ -0,0 +1 @@
1
+ import e from"@arcgis/core/Color";import t from"@arcgis/core/Graphic";import o from"@arcgis/core/geometry/Point";import n from"@arcgis/core/layers/GeoJSONLayer";import r from"@arcgis/core/layers/GraphicsLayer";import s from"@arcgis/core/symbols/SimpleFillSymbol";import i from"@arcgis/core/symbols/SimpleLineSymbol";import a from"@arcgis/core/symbols/TextSymbol.js";import{project as l}from"../../utilities/geometry.js";import{delay as c}from"../../utilities/promise.js";import{getDefaultSymbol as x}from"../convert.js";import{normalizeFillStyle as d,normalizeLineOutline as y,intToRGB as p,deriveAnnotationMinScale as f}from"./_dxfFunctions.js";export class DxfToGeoJsonLineMapper{dxfContext;constructor(e){this.dxfContext=e,this.dxfContext.lastLineEnd=void 0,this.dxfContext.lastLineLayer=void 0}async processLine(e){const{vertices:t}=e;if(!t||t.length<2)return;const o=t[0],n=t[1];if(!o||!n)return;const[r,s]=await Promise.all([this.dxfContext.convertToSpatialReference(o.x,o.y),this.dxfContext.convertToSpatialReference(n.x,n.y)]),i=e.layer||"default",a={type:"Feature",geometry:{type:"LineString",coordinates:[r,s]},properties:{...e}};if(this.dxfContext.lastLineEnd&&this.dxfContext.lastLineLayer===i&&this._isSamePoint(this.dxfContext.lastLineEnd,r)){const e=this.dxfContext.lineFeatures.at(-1);if("LineString"===e?.geometry?.type){e.geometry.coordinates.push(s)}else this.dxfContext.lineFeatures.push(a)}else this.dxfContext.lineFeatures.push(a);this.dxfContext.lastLineEnd=s,this.dxfContext.lastLineLayer=i;const l=this.dxfContext.dxf.tables?.layer?.layers?.[i],c=e.color??l?.color??x(this.dxfContext.colorIndex++,"polyline").color,d=this._getLayerColor(e,c),y=`${e.layer}-${e.type}-${e.handle}`;this.dxfContext.renderer_Object_Line[y]={value:e.layer||"default",symbol:{type:"simple-line",color:d,width:e.lineweight||1.5,style:(()=>{const t=e.lineType&&this.dxfContext.dxf.tables?.lineType?.lineTypes?.[e.lineType];return"object"==typeof t&&t?.pattern?{pattern:t.pattern.map((e=>parseFloat(e)))}:"solid"})()}}}async processPolyline(t){const o=await this._getPolylineCoordinates(t),n=!!t.closed;n&&o.length>0&&this._ensureClosed(o);const r=this.dxfContext.dxf.tables?.layer?.layers?.[t.layer];let s;s=t.color,void 0!==s&&0!==s&&256!==s||(s=r?.color),void 0===s&&(s=x(this.dxfContext.colorIndex++,"polyline")?.color??new e("black"));const i="number"==typeof s?this.dxfContext.intToRGB(s):s,a=this._buildPolylineFeature(t,o,n,s);if(n)if(Array.isArray(i))this._applyPolygonRenderer(t,i,a);else if(i&&"object"==typeof i&&"r"in i){const e=[i.r,i.g,i.b,1];this._applyPolygonRenderer(t,e,a)}else{const o=x(this.dxfContext.colorIndex++,"polygon").color,n=o instanceof e?o.toRgba():o;this._applyPolygonRenderer(t,n,a)}else this._applyLineRenderer(t,a)}async processLWPolyline(e){const t=this._buildBulgeInterpolatedPoints(e),n=await this.dxfContext.projectMany(t.map((e=>new o({x:e.x,y:e.y,spatialReference:this.dxfContext.sourceSR})))),r=n[0],s=n[n.length-1],i=!!r&&!!s&&Math.abs(r[0]-s[0])<1e-6&&Math.abs(r[1]-s[1])<1e-6,a=Boolean(e.shape&&(e.closed||i)),l=this.dxfContext.dxf.tables?.layer?.layers?.[e.layer],c=e.color??l?.color??x(this.dxfContext.colorIndex++,"polyline").color,d=this._buildLWPolylineFeature(e,n,a,c);a?this._applyPolygonRenderer(e,this._getLayerColor(e,c),d):this._applyLineRenderer(e,d)}async processArc(e){const t=(e.startAngle??0)*(Math.PI/180),n=(e.endAngle??0)*(Math.PI/180),r=n-t,s=e.layer||"default",i=this.dxfContext.dxf.tables?.layer?.layers?.[s],a=Math.abs(n-t),c=Math.min(720,Math.max(48,Math.ceil(a*e.radius/2))),d=r/c,y=[];for(let n=0;n<=c;n++){const r=t+d*n,s=e.center.x+e.radius*Math.cos(r),i=e.center.y+e.radius*Math.sin(r);y.push(new o({x:s,y:i,spatialReference:this.dxfContext.sourceSR}))}const p=(await l(y,this.dxfContext.targetSR)).filter((e=>void 0!==e.longitude&&void 0!==e.latitude)).map((e=>[e.longitude,e.latitude])),f={type:"Feature",geometry:{type:"LineString",coordinates:p},properties:{...e}};if(this.dxfContext.lastLineEnd&&this.dxfContext.lastLineLayer===s&&p[0]&&this._isSamePoint(this.dxfContext.lastLineEnd,p[0])){const e=this.dxfContext.lineFeatures.at(-1);if("LineString"===e?.geometry?.type){e.geometry.coordinates.push(...p.slice(1))}else this.dxfContext.lineFeatures.push(f)}else this.dxfContext.lineFeatures.push(f);this.dxfContext.lastLineEnd=p.at(-1)??void 0,this.dxfContext.lastLineLayer=s;const h=`${e.layer}-${e.type}-${e.handle}`;this.dxfContext.renderer_Object_Line[h]={value:s,symbol:{type:"simple-line",color:this.dxfContext.intToRGB(Number(i?.color??x(this.dxfContext.colorIndex++,"polyline").color)),width:1.5,style:(()=>{const t=this.dxfContext.dxf.tables.lineType?.lineTypes?.[e.lineType],o="object"==typeof t&&void 0!==t?t:void 0;return o?.pattern?{pattern:o.pattern.map((e=>parseFloat(e)))}:"solid"})()}}}lineToGeoJSON(){this.dxfContext.lineFeatures=this._mergeConnectedLinesAndArcs(this.dxfContext.lineFeatures);const e={type:"FeatureCollection",features:this.dxfContext.lineFeatures},t=new Blob([JSON.stringify(e)],{type:"application/json"}),o=URL.createObjectURL(t),r=new n({url:o,id:`dxf-lines-${this.dxfContext.sanitizedFileName}-${(new Date).getTime()}`,title:`${this.dxfContext.fileName} - Lines`,visible:!0,labelsVisible:!0,renderer:{type:"unique-value",field:"layer",defaultSymbol:{type:"simple-line",color:x(this.dxfContext.colorIndex++,"polyline").color,width:1.5,style:"solid"},uniqueValueInfos:Object.values(this.dxfContext.renderer_Object_Line).map((e=>{const t="object"==typeof e.symbol.style?"dash":e.symbol.style??"solid";return{value:e.value,symbol:{type:"simple-line",color:e.symbol.color??x(this.dxfContext.colorIndex++,"polyline").color,width:e.symbol.width??1.5,style:t}}}))}});this.dxfContext.subLayers.push(r)}_getLayerColor(t,o){if("number"==typeof o)return this.dxfContext.intToRGB(o);if(Array.isArray(o))return o;if(o instanceof e)return o.toRgba();const n=x(this.dxfContext.colorIndex++,"polyline").color;if(n instanceof e)return n.toRgba();if(Array.isArray(n))return n;if("number"==typeof n)return this.dxfContext.intToRGB(n);const r=x(this.dxfContext.colorIndex++,"polyline").color;return r instanceof e?r.toRgba():Array.isArray(r)?r:[0,0,0,1]}_interpolateBulge(e,t,o,n=16){if(Math.abs(o)<1e-9)return[[t.x,t.y]];const r=t.x-e.x,s=t.y-e.y,i=Math.hypot(r,s);if(i<1e-9)return[[t.x,t.y]];const a=4*Math.atan(o),l=Math.abs(i/(2*Math.sin(a/2))),c=e.x+r/2,x=e.y+s/2,d=Math.sqrt(Math.max(0,l*l-i/2*(i/2))),y=c+d*(-s/i*Math.sign(o)),p=x+d*(r/i*Math.sign(o)),f=Math.atan2(e.y-p,e.x-y),h=[],u=a/n;for(let e=1;e<=n;e++){const t=f+e*u;h.push([y+l*Math.cos(t),p+l*Math.sin(t)])}return h}_buildBulgeInterpolatedPoints(e){const t=[];e.vertices.length>0&&e.vertices[0]&&t.push({x:e.vertices[0].x,y:e.vertices[0].y});for(let o=0;o<e.vertices.length-1;o++){const n=e.vertices[o],r=e.vertices[o+1];if(!n||!r)continue;const s=n.bulge??0,i=this._interpolateBulge(n,r,s,16);for(const[e,o]of i)t.push({x:e,y:o})}if((e.closed||e.shape)&&e.vertices.length>1){const o=e.vertices[0],n=e.vertices[e.vertices.length-1];if(o&&n&&(o.x!==n.x||o.y!==n.y)){const e=n.bulge??0,r=this._interpolateBulge(n,o,e,16);for(const[e,o]of r)t.push({x:e,y:o})}}return t}_buildLWPolylineFeature(e,t,o,n){return{type:"Feature",geometry:o?{type:"Polygon",coordinates:[t]}:{type:"LineString",coordinates:t},properties:{...e,color:n}}}async _getPolylineCoordinates(e){const t=e.vertices.map((e=>new o({x:e.x,y:e.y,spatialReference:this.dxfContext.sourceSR})));return(await l(t,this.dxfContext.targetSR)).filter((e=>!!e&&void 0!==e.longitude&&void 0!==e.latitude)).map((e=>[e.longitude,e.latitude]))}_ensureClosed(e){const t=e[0],o=e[e.length-1];t&&o&&(t[0]!==o[0]||t[1]!==o[1])&&e.push(t)}_buildPolylineFeature(e,t,o,n){return{type:"Feature",geometry:o?{type:"Polygon",coordinates:[t]}:{type:"LineString",coordinates:t},properties:{...e,color:n}}}_applyPolygonRenderer(t,o,n){this.dxfContext.polygonFeatures.push(n);const r=`${t.layer}-${t.type}-${t.handle}`,s=o instanceof e?o.toRgba():o;this.dxfContext.renderer_Object_Polygon[r]={value:t.layer||"default",symbol:{type:"simple-fill",style:t.closed?"solid":"none",color:s,outline:{color:s,width:t.width??1.5}}}}_applyLineRenderer(t,o){this.dxfContext.lineFeatures.push(o);const n=o.properties?.color;let r;if(n instanceof e)r=n.toRgba();else if(Array.isArray(n)&&n.every((e=>"number"==typeof e)))r=n;else{const e="number"==typeof n?n:0;r=this.dxfContext.intToRGB(e)}const s=`${t.layer}-${t.type}-${t.handle}`;this.dxfContext.renderer_Object_Line[s]={value:t.layer||"default",symbol:{type:"simple-line",color:r,width:t.lineweight||1.5,style:(()=>{const e=t.lineType&&this.dxfContext.dxf.tables.lineType?.lineTypes[t.lineType],o="object"==typeof e&&void 0!==e?e:void 0;return mapDXFLineTypeToEsri(t.lineType,o)})()}}}_isSamePoint(e,t,o=1e-6){return Math.abs(e[0]-t[0])<=o&&Math.abs(e[1]-t[1])<=o}_mergeConnectedLinesAndArcs(e){const t=[];for(const o of e){const e=t[t.length-1],n="LineString"===e?.geometry?.type,r="LineString"===o?.geometry?.type,s=n?e.geometry.coordinates:void 0,i=r?o.geometry.coordinates:void 0,a=s?.at(-1),l=i?.at(0);e&&a&&l&&e.properties?.layer===o.properties?.layer&&this._isSamePoint(a,l)?e.geometry.coordinates.push(...o.geometry.coordinates.slice(1)):t.push(o)}return t}}export class DxfToGeoJsonPolygonMapper{dxfContext;constructor(e){this.dxfContext=e}async processSolid(e){const t=e.points.map((e=>new o({x:e.x,y:e.y,spatialReference:this.dxfContext.sourceSR}))),n=(await l(t,this.dxfContext.targetSR)).filter((e=>!!e&&void 0!==e.longitude&&void 0!==e.latitude)).map((e=>[e.longitude,e.latitude]));if(n.length>0){const e=n[0],t=n[n.length-1];e[0]===t[0]&&e[1]===t[1]||n.push(e)}const r=this.dxfContext.dxf.tables?.layer?.layers?.[e.layer],s={type:"Feature",geometry:{type:"Polygon",coordinates:[n]},properties:{...e}};this.dxfContext.polygonFeatures.push(s);const i=r?.color??x(this.dxfContext.colorIndex++,"polygon").color,a=this.dxfContext.intToRGB(Number(i??0)),c=`${e.layer}-${e.type}-${e.handle}`;this.dxfContext.renderer_Object_Polygon[c]={value:e.layer||"default",symbol:{type:"simple-fill",style:"solid",color:[...a.slice(0,3),.5],outline:{color:this.dxfContext.intToRGB(Number(i??0)),width:1.5}}}}async processCircle(e){const t=e.center.x,n=e.center.y,r=Math.min(64,Math.max(16,Math.ceil(e.radius/5))),s=2*Math.PI/r,i=[];for(let a=0;a<=r;a++){const r=a*s,l=t+e.radius*Math.cos(r),c=n+e.radius*Math.sin(r);i.push(new o({x:l,y:c,spatialReference:this.dxfContext.sourceSR}))}const a=(await this.dxfContext.projectMany(i)).map((e=>[e[0],e[1]])),l=a[0],c=a[a.length-1];l&&c&&(l[0]!==c[0]||l[1]!==c[1])&&a.push(l);const d={type:"Feature",geometry:{type:"Polygon",coordinates:[a]},properties:{...e}};this.dxfContext.polygonFeatures.push(d);const y=this.dxfContext.dxf.tables?.layer?.layers?.[e.layer||"default"],p=e.color??y?.color??x(this.dxfContext.colorIndex++,"polygon").color;let f;f=Array.isArray(p)?p:"object"==typeof p&&"toRgba"in p?p.toRgba():this.dxfContext.intToRGB(p);const h=`${e.layer}-${e.type}-${e.handle}`;this.dxfContext.renderer_Object_Polygon[h]={value:e.layer||"default",symbol:{type:"simple-fill",style:"solid",color:f,outline:{color:f}}}}polygonToGeoJSON(){const t={type:"FeatureCollection",features:this.dxfContext.polygonFeatures},o=new Blob([JSON.stringify(t)],{type:"application/json"}),r=URL.createObjectURL(o);this.dxfContext.subLayers.push(new n({url:r,id:`dxf-polygons-${this.dxfContext.sanitizedFileName}-${(new Date).getTime()}`,title:`${this.dxfContext.fileName} - Polygons`,visible:!0,labelsVisible:!0,renderer:{type:"unique-value",field:"layer",defaultSymbol:(()=>{let e;const t=x(this.dxfContext.colorIndex++,"polygon");return t?.toJSON&&(e=t.toJSON()),{type:"simple-fill",style:d(e?.style),color:e?.color??x(this.dxfContext.colorIndex++,"polygon").color,outline:y(e?.outline)}})(),uniqueValueInfos:Object.values(this.dxfContext.renderer_Object_Polygon).map((t=>{const o=new i({color:t.symbol.outline?.color?new e(t.symbol.outline.color):new e(t.symbol.color??x(this.dxfContext.colorIndex++,"polygon").color),width:t.symbol.outline?.width??1.5}),n=t.symbol.color?[...t.symbol.color.slice(0,3),.3]:x(this.dxfContext.colorIndex++,"polygon").color,r=new s({style:"solid",color:new e(n),outline:o});return{value:t.value,symbol:r}}))}}))}}export class DxfToGeoJsonTextMapper{dxfContext;constructor(e){this.dxfContext=e}async processText(e){if(e.block)return;const[t,o]=await this.dxfContext.convertToSpatialReference(e.startPoint.x,e.startPoint.y);this.dxfContext.textFeatures.push({type:"Feature",geometry:{type:"Point",coordinates:[t,o]},properties:{...e}})}async processMText(e){const[t,o]=await this.dxfContext.convertToSpatialReference(e.position.x,e.position.y);this.dxfContext.textFeatures.push({type:"Feature",geometry:{type:"Point",coordinates:[t,o]},properties:{...e}})}async processAttDef(e){const[t,o]=await this.dxfContext.convertToSpatialReference(e.startPoint.x,e.startPoint.y),n=e.endPoint??e.startPoint,[r,s]=await this.dxfContext.convertToSpatialReference(n.x,n.y);this.dxfContext.textFeatures.push({type:"Feature",geometry:{type:"Point",coordinates:[t,o]},properties:{...e,startPoint:{x:t,y:o},endPoint:{x:r,y:s}}})}AnnotationToGeoJSON(){const e={1:"above-left",2:"above-center",3:"above-right",4:"center-left",5:"center-center",6:"center-right",7:"below-left",8:"below-center",9:"below-right"},t=new Map([[0,"left"],[2,"right"],[4,"center"]]),o=new Map([[0,"baseline"],[1,"bottom"],[2,"middle"],[3,"top"]]),n=this.dxfContext.textFeatures.map((n=>this._createTextGraphic(n,e,t,o))).filter((e=>null!==e)),s=new r({title:`${this.dxfContext.fileName??"dxf"} - Annotations`,id:`dxf-annotations-${this.dxfContext.sanitizedFileName??"dxf"}-${(new Date).getTime()}`,visible:!0,graphics:n});this.dxfContext.subLayers.push(s);const i=this.getMaximumFontSize(n);s.minScale=f(s.fullExtent??void 0,n.length,i),s.maxScale=0}getMaximumFontSize(e){let t=12;return e.forEach((e=>{if(!e)return;const o=e.attributes?.fontSize;"number"==typeof o&&Number.isFinite(o)&&(t=Math.max(t,o))})),t+2}_createTextGraphic(e,n,r,s){if("Point"!==e.geometry.type)return;const i=e.properties??{},l=this._getTextString(i);if(!l)return;const c=e.geometry.coordinates,x=new o({x:c[0],y:c[1],spatialReference:{wkid:4326}}),d=this._getTextColor(i),y=this._getFontSize(i),p=this._getRotation(i),{xoffset:f,yoffset:h}=this._getOffsets(i),{labelPlacement:u,horizontal:m,vertical:g}=this._getAlignment(i,n,r,s);return new t({geometry:x,symbol:new a({text:l,color:d,angle:p,xoffset:f,yoffset:h,horizontalAlignment:m,verticalAlignment:g,font:{family:"Arial",size:y}}),attributes:{...i,text:l,rotation:p,fontSize:y,horizontal:m,vertical:g,xoffset:f,yoffset:h,labelPlacement:u},popupTemplate:{title:"{text}",content:[{type:"fields",fieldInfos:Object.keys(i).map((e=>({fieldName:e,label:e})))}]}})}_getTextString(e){if(!e)return"";const t=String(e.text??"").trim(),o=String(e.prompt??"").trim(),n=t||o;return n||""}_getTextColor(e){const t=String(e?.layer||"0"),o=e?.color??this.dxfContext.dxf.tables?.layer?.layers?.[t]?.color??x(this.dxfContext.colorIndex++,"point").color;return this.dxfContext.intToRGB(o)}_getFontSize(e){let t=4*(e?.height??e?.textHeight??3);return t=Math.max(12,Math.min(t,30)),t}_getRotation(e){const t=String(e?.type??"").toUpperCase(),o=Number(e?.rotation??0);if("TEXT"===t)return-o;if("MTEXT"===t)return-o;if("ATTDEF"===t||"ATTRIB"===t){if(0!==o)return-o;if(e?.startPoint&&e?.endPoint){const{x:t,y:o}=e.startPoint,{x:n,y:r}=e.endPoint;if(t!==n||o!==r)return-180*Math.atan2(r-o,n-t)/Math.PI}return-o}if(e?.startPoint&&e?.endPoint){const{x:t,y:o}=e.startPoint,{x:n,y:r}=e.endPoint;return-180*Math.atan2(r-o,n-t)/Math.PI}return-o}_getOffsets(e){return{xoffset:Number(e?.xScale??0),yoffset:Number(e?.yScale??0)}}_getAlignment(e,t,o,n){return{labelPlacement:t[Number(e?.attachmentPoint??1)]??"above-left",horizontal:o.get(Number(e?.halign??e?.horizontalJustification))??"left",vertical:n.get(Number(e?.valign??e?.verticalJustification))??"baseline"}}}export class DxfToGeoJsonInsertBlockMapper{dxfContext;constructor(e){this.dxfContext=e}async processInsertFunction(e){if(!e.name||!this.dxfContext.dxf.blocks?.[e.name])return;const t=this.dxfContext.dxf.blocks[e.name],o=e.rotation||0,n={x:e.xScale??1,y:e.yScale??1,z:e.zScale??1},r=e.position||{x:0,y:0},[s,i]=await this.dxfContext.convertToSpatialReference(r.x,r.y);this._createInsertPointFeature(e,t,o,s,i);const a=(e.layer||"default").toString();this.dxfContext.renderer_Object_Point[a]=this._createLayerSymbol(a,e),await this._processBlockEntities(t,e,o,n,r)}async processPoint(t){const[o,n]=await this.dxfContext.convertToSpatialReference(t.position.x,t.position.y),r=this.dxfContext.dxf.header?.$PDMODE||0;let s="circle";if(32&~r)if(64&~r)switch(7&r){case 0:case 1:s="circle";break;case 2:s="cross";break;case 3:s="x"}else s="square";else s="circle";const i=(t.layer||"default").toString(),a=this.dxfContext.dxf.tables?.layer?.layers?.[i],l=t.color??a?.color??x(this.dxfContext.colorIndex++,"point").color,c=l instanceof e?l.toRgba():Array.isArray(l)?l:this.dxfContext.intToRGB(Number(l??0));this.dxfContext.pointFeatures.push({type:"Feature",geometry:{type:"Point",coordinates:[o,n]},properties:{...t}}),this.dxfContext.renderer_Object_Point[i]={value:i,symbol:{type:"simple-marker",style:s,size:this.dxfContext.dxf.header?.$PDSIZE||5,color:c}}}async processInsert(e){const t={...e};t.xScale=e.xScale??1,t.yScale=e.yScale??1,t.zScale=e.zScale??1,t.rotation=e.rotation??0,await this.processInsertFunction(t)}pointToGeoJSON(){const e={type:"FeatureCollection",features:this.dxfContext.pointFeatures},t=new Blob([JSON.stringify(e)],{type:"application/json"}),o=URL.createObjectURL(t),r=new n({url:o,id:`dxf-points-${this.dxfContext.sanitizedFileName}-${(new Date).getTime()}`,title:`${this.dxfContext.fileName} - Points`,labelsVisible:!0,renderer:{type:"unique-value",field:"layer",defaultSymbol:{type:"simple-marker",style:"circle",color:x(this.dxfContext.colorIndex++,"point").color,size:6},uniqueValueInfos:Object.values(this.dxfContext.renderer_Object_Point).map((e=>({value:e.value,symbol:{type:"simple-marker",style:"circle",size:e.symbol?.size||6,color:e.symbol.color??x(this.dxfContext.colorIndex++,"point").color}})))}});this.dxfContext.subLayers.push(r)}_createInsertPointFeature(e,t,o,n,r){this.dxfContext.pointFeatures.push({type:"Feature",geometry:{type:"Point",coordinates:[n,r]},properties:{layer:e.layer||"default",type:"INSERT",blockName:e.name,rotation:o,blockType:t?.name??e.name,color:e.color??this.dxfContext.dxf.tables?.layer?.layers?.[e.layer]?.color??x(this.dxfContext.colorIndex++,"polyline").color,text:t?.name??e.name}})}_createLayerSymbol(e,t){return{value:e,symbol:{type:"simple-marker",style:"circle",size:5,color:this.dxfContext.intToRGB(this.dxfContext.dxf.tables?.layer?.layers?.[t.layer]?.color??0)}}}_normalizeBlockEntities(e){const t=e.entities;return Array.isArray(t)?t:void 0===t?[]:"function"==typeof t[Symbol.iterator]?Array.from(t):Array.isArray(t.entities)?t.entities:"object"==typeof t&&void 0!==t?Object.values(t):[]}async _processBlockEntities(e,t,o,n,r){const s=this._normalizeBlockEntities(e);if(0!==s.length)for(const e of s){if(!e||"object"!=typeof e)continue;const s=e.type;if("BLOCK"===s||"ENDBLK"===s)continue;const i=JSON.parse(JSON.stringify(e));if(i.layer=e.layer&&"0"!==e.layer?e.layer:String(t.layer),0===e.color)i.color=t.color;else if(256===e.color||void 0===e.color){const e=this.dxfContext.dxf.tables?.layer?.layers?.[String(t.layer)];i.color=e?.color}try{this._transformEntityGeometry(i,n,o,r),this._adjustEntityAttributes(i,n,o,t.name),await this.dxfContext.dxfEntities([i])}catch{continue}}}_transformEntityGeometry(e,t,o,n){const r=o*Math.PI/180,s=(e,o)=>({x:e*t.x*Math.cos(r)-o*t.y*Math.sin(r)+n.x,y:e*t.x*Math.sin(r)+o*t.y*Math.cos(r)+n.y});e.vertices&&(e.vertices=e.vertices.map((e=>{const t=s(e.x,e.y);return{x:t.x,y:t.y,bulge:e.bulge}}))),e.center&&(e.center=s(e.center.x,e.center.y)),e.position&&(e.position=s(e.position.x,e.position.y))}_adjustEntityAttributes(e,t,o,n){e.radius&&(e.radius*=Math.max(t.x,t.y)),e.height&&(e.height*=t.y),void 0!==e.rotation&&(e.rotation=(e.rotation+o)%360),e.blockName=String(n)}}export function mapDXFLineTypeToEsri(e,t){if(!e)return"solid";const o=e.toUpperCase(),n=function(e,t){if(!e)return;const o=e.toUpperCase().trim(),n={BYLAYER:"solid",BYBLOCK:"solid",CONTINUOUS:"solid",HIDDEN:"dash",DASHED:"dash",DASHEDX2:"dash",DASHED2:"dash",CENTER:"dash-dot",CENTERX2:"dash-dot",CENTER2:"dash-dot",DASHDOT:"dash-dot",DOTTED:"dot",DIVIDE:"short-dash",DIVIDEX2:"short-dash-dot",DIVIDE2:"short-dash-dot"};if(n[o])return n[o];if(t?.length){const e=Math.abs(t[0]??0),o=Math.abs(t[1]??0);if(2===t.length)return e<8&&o<6?"short-dash":e>=8&&e<=15&&o>=6&&o<=15?"dash":"long-dash";if(4===t.length)return e<6&&o<6?"short-dash-dot":e>=6&&e<=15&&o>=6&&o<=15?"dash-dot":"long-dash-dot"}return}(o,t?.pattern?.map((e=>parseFloat(e))));if(n)return n;const r=function(e){const t=e.toUpperCase();return t.includes("LONG")?"long-dash":t.includes("DOUBLE")?"long-dash-dot":t.includes("PHANTOM")?"dash-dot":void 0}(o);if(r)return r;const s=function(e){if(e?.pattern&&Array.isArray(e.pattern)){const t=e.pattern,o=t.some((e=>parseFloat(e)>.2)),n=t.some((e=>0===parseFloat(e)));return o&&!n?"dash":!o&&n?"dot":o&&n?"dash-dot":"solid"}return}(t);return s||"solid"}export class DxfEntityProcessor{dxfContext;entityHandlers;constructor(e,t,o={}){const n={dxf:{header:{},tables:{viewPort:{handle:"",ownerHandle:"",viewPorts:[]},lineType:{handle:"",ownerHandle:"",lineTypes:{}},layer:{handle:"",ownerHandle:"",layers:{}}},entities:[],blocks:{}},renderer_Object_Point:{},renderer_Object_Line:{},renderer_Object_Polygon:{},sourceSR:e,targetSR:t,subLayers:[],pointFeatures:[],lineFeatures:[],polygonFeatures:[],textFeatures:[],async dxfEntities(){},convertToSpatialReference:async()=>[0,0],projectMany:async()=>[],intToRGB:p,colorIndex:0,...o};n.dxfToGeoJsonLineMapper=new DxfToGeoJsonLineMapper(n),n.dxfToGeoJsonPolygonMapper=new DxfToGeoJsonPolygonMapper(n),n.dxfToGeoJsonTextMapper=new DxfToGeoJsonTextMapper(n),n.dxfToGeoJsonInsertBlockMapper=new DxfToGeoJsonInsertBlockMapper(n),this.dxfContext=n,this.dxfContext.convertToSpatialReference=(e,t)=>this.convertToSpatialReference(e,t),this.dxfContext.projectMany=e=>this.projectMany(e),this.dxfContext.dxfEntities=async e=>this.process(e),this.entityHandlers={POINT:e=>this.dxfContext.dxfToGeoJsonInsertBlockMapper.processPoint(e),INSERT:e=>this.dxfContext.dxfToGeoJsonInsertBlockMapper.processInsert(e),LINE:async e=>{e.vertices?.length>=2&&await this.dxfContext.dxfToGeoJsonLineMapper.processLine(e)},ARC:async e=>{e.center&&void 0!==e.radius&&await this.dxfContext.dxfToGeoJsonLineMapper.processArc(e)},LWPOLYLINE:async e=>{Array.isArray(e.vertices)&&await this.dxfContext.dxfToGeoJsonLineMapper.processLWPolyline(e)},POLYLINE:async e=>{Array.isArray(e.vertices)&&await this.dxfContext.dxfToGeoJsonLineMapper.processPolyline(e)},SOLID:async e=>{e.points.length>=3&&await this.dxfContext.dxfToGeoJsonPolygonMapper.processSolid(e)},CIRCLE:async e=>{e.center&&e.radius&&await this.dxfContext.dxfToGeoJsonPolygonMapper.processCircle(e)},TEXT:e=>this.dxfContext.dxfToGeoJsonTextMapper.processText(e),MTEXT:async e=>{e.position&&await this.dxfContext.dxfToGeoJsonTextMapper.processMText(e)},ATTDEF:async e=>{e.startPoint&&await this.dxfContext.dxfToGeoJsonTextMapper.processAttDef(e)}}}getContext(){return this.dxfContext}async convertToSpatialReference(e,t){const n=new o({x:e,y:t,spatialReference:this.dxfContext.sourceSR}),[r]=await l([n],this.dxfContext.targetSR);return r?[r.longitude??0,r.latitude??0]:[0,0]}async projectMany(e){return(await l(e,this.dxfContext.targetSR)).map(((t,o)=>{const n=e[o];return[t?.longitude??n.x,t?.latitude??n.y]}))}async process(e){const t=Array.isArray(e)?e:[e];for(const e of t){if(!e||"BLOCK"===e.type||"ENDBLK"===e.type)continue;const t=this.entityHandlers[e.type];t&&await t(e)}}async processAll(){if(this.dxfContext.dxf.entities?.length>0){const e=50;for(let t=0;t<this.dxfContext.dxf.entities.length;t+=e){const o=this.dxfContext.dxf.entities.slice(t,t+e);await c(),await this.process(o)}}return await Promise.all([this.dxfContext.polygonFeatures.length>0&&this.dxfContext.dxfToGeoJsonPolygonMapper.polygonToGeoJSON(),this.dxfContext.lineFeatures.length>0&&this.dxfContext.dxfToGeoJsonLineMapper.lineToGeoJSON(),this.dxfContext.pointFeatures.length>0&&this.dxfContext.dxfToGeoJsonInsertBlockMapper.pointToGeoJSON(),this.dxfContext.textFeatures.length>0&&this.dxfContext.dxfToGeoJsonTextMapper.AnnotationToGeoJSON()].filter(Boolean)),this.dxfContext.subLayers}}
@@ -0,0 +1,82 @@
1
+ import type SimpleFillSymbol from "@arcgis/core/symbols/SimpleFillSymbol";
2
+ import type { ILineType } from "dxf-parser";
3
+ /**
4
+ * Maps a DXF line type name and definition to a corresponding Esri
5
+ * SimpleLineSymbol style.
6
+ *
7
+ * @param lineTypeName The name of the DXF line type.
8
+ * @param lineTypeObj The DXF line type definition object.
9
+ * @returns The mapped Esri line style (e.g., "solid", "dash", "dot").
10
+ */
11
+ export declare function mapDXFLineTypeToEsri(lineTypeName: string, lineTypeObj: ILineType | undefined): "solid" | "dash" | "dot" | "dash-dot" | "long-dash" | "long-dash-dot" | "short-dash" | "short-dash-dot";
12
+ /**
13
+ * Maps basic DXF line type names to Esri line styles.
14
+ *
15
+ * @param name The name of the line type.
16
+ * @param pattern The numeric pattern of the line type.
17
+ * @returns The mapped Esri line style, or undefined if no match is found.
18
+ */
19
+ export declare function mapBasicLineType(name: string, pattern?: number[]): "solid" | "dash" | "dash-dot" | "dot" | "short-dash" | "short-dash-dot" | "long-dash" | "long-dash-dot" | undefined;
20
+ /**
21
+ * Maps ISO line type patterns based on name conventions.
22
+ *
23
+ * @param name The name of the line type.
24
+ * @returns The mapped Esri line style, or undefined if no match is found.
25
+ */
26
+ export declare function mapIsoPatterns(name: string): "long-dash" | "long-dash-dot" | "dash-dot" | undefined;
27
+ /**
28
+ * Maps a DXF line type pattern definition to an Esri line style.
29
+ *
30
+ * @param lineTypeObj The DXF line type definition object.
31
+ * @returns The mapped Esri line style, or undefined if the pattern cannot be
32
+ * mapped.
33
+ */
34
+ export declare function mapLineTypePattern(lineTypeObj: ILineType | undefined): "solid" | "dash" | "dot" | "dash-dot" | undefined;
35
+ /**
36
+ * Converts a DXF integer color value to an RGB array.
37
+ *
38
+ * @param colorInt Integer color value.
39
+ * @returns RGB array.
40
+ */
41
+ export declare function intToRGB(colorInt: number): number[];
42
+ /**
43
+ * Represents the valid style values for an Esri SimpleFillSymbol.
44
+ */
45
+ export type SimpleFillStyle = SimpleFillSymbol["style"];
46
+ export declare const VALID_FILL_STYLES: SimpleFillStyle[];
47
+ /**
48
+ * Normalizes style strings (including legacy esriSFS* values) to valid
49
+ * SimpleFillSymbol styles.
50
+ *
51
+ * @param style The style value to normalize.
52
+ */
53
+ export declare function normalizeFillStyle(style?: unknown): SimpleFillStyle;
54
+ /**
55
+ * Normalizes an outline object into a simple line symbol properties object.
56
+ *
57
+ * @param outline The outline properties to normalize.
58
+ * @param outline.color The color of the outline.
59
+ * @param outline.width The width of the outline.
60
+ * @param outline.type The type of the outline.
61
+ * @returns An object containing `type`, `color`, and `width` for a
62
+ * SimpleLineSymbol.
63
+ */
64
+ export declare function normalizeLineOutline(outline?: {
65
+ color?: number[];
66
+ width?: number;
67
+ type?: string;
68
+ }): {
69
+ type: "simple-line";
70
+ color: number[];
71
+ width: number;
72
+ };
73
+ /**
74
+ * Derives a minimum scale for annotation visibility based on extent and text
75
+ * density.
76
+ *
77
+ * @param extent The extent of the annotation layer.
78
+ * @param textCount The total number of text elements.
79
+ * @param maxFontSize The maximum font size used in the annotations.
80
+ * @returns The calculated minimum scale.
81
+ */
82
+ export declare function deriveAnnotationMinScale(extent: __esri.Extent | undefined, textCount: number, maxFontSize: number): number;