@design-core/core 0.0.1 → 0.0.3
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/.eslintrc.json +14 -7
- package/.github/workflows/DesignCoreQA.yml +3 -1
- package/README.md +11 -4
- package/TODO.md +19 -0
- package/core/core/core.js +49 -42
- package/core/designCore.js +61 -2
- package/core/dimensions/alignedDimension.js +142 -0
- package/core/dimensions/angularDimension.js +550 -0
- package/core/dimensions/baseCircularDimension.js +244 -0
- package/core/dimensions/baseDimension.js +558 -0
- package/core/dimensions/baseLinearDimension.js +371 -0
- package/core/dimensions/diametricDimension.js +82 -0
- package/core/dimensions/dimension.js +298 -0
- package/core/dimensions/linearDimension.js +29 -0
- package/core/dimensions/radialDimension.js +78 -0
- package/core/dimensions/rotatedDimension.js +167 -0
- package/core/entities/arc.js +314 -60
- package/core/entities/arctext.js +642 -0
- package/core/entities/basePolyline.js +553 -94
- package/core/entities/circle.js +181 -54
- package/core/entities/entity.js +154 -74
- package/core/entities/hatch.js +807 -0
- package/core/entities/insert.js +200 -39
- package/core/entities/line.js +196 -134
- package/core/entities/lwpolyline.js +21 -44
- package/core/entities/point.js +194 -29
- package/core/entities/polyline.js +54 -7
- package/core/entities/rectangle.js +43 -13
- package/core/entities/solid.js +43 -6
- package/core/entities/text.js +324 -181
- package/core/lib/boundingBox.js +73 -13
- package/core/lib/canvas.js +256 -65
- package/core/lib/clipboard.js +198 -0
- package/core/lib/colour.js +144 -0
- package/core/lib/colours.js +367 -301
- package/core/lib/commandLine.js +16 -28
- package/core/lib/commandManager.js +115 -58
- package/core/lib/constants.js +23 -0
- package/core/lib/dxf/dxf.js +249 -34
- package/core/lib/dxf/dxfFile.js +23 -38
- package/core/lib/dxf/dxfIterator.js +17 -5
- package/core/lib/dxf/dxfRead.js +23 -7
- package/core/lib/dxf/dxfWrite.js +39 -129
- package/core/lib/dxf/handleManager.js +97 -0
- package/core/lib/dxf/sections/blocks.js +16 -2
- package/core/lib/dxf/sections/entities.js +17 -3
- package/core/lib/dxf/sections/header.js +10 -1
- package/core/lib/dxf/sections/objects.js +36 -0
- package/core/lib/dxf/sections/section.js +43 -5
- package/core/lib/dxf/sections/tables.js +17 -3
- package/core/lib/entityManager.js +178 -0
- package/core/lib/fileio.js +14 -4
- package/core/lib/headers.js +229 -0
- package/core/lib/input.js +46 -0
- package/core/lib/inputManager.js +199 -194
- package/core/lib/intersect.js +341 -468
- package/core/lib/logging.js +25 -1
- package/core/lib/matrix.js +6 -8
- package/core/lib/mouse.js +24 -79
- package/core/lib/patterns.js +690 -0
- package/core/lib/promptOptions.js +133 -0
- package/core/lib/scene.js +71 -174
- package/core/lib/selectionManager.js +74 -48
- package/core/lib/selectionWindow.js +24 -10
- package/core/lib/settings.js +18 -11
- package/core/lib/snapping.js +129 -21
- package/core/lib/stateManager.js +288 -0
- package/core/lib/strings.js +57 -5
- package/core/lib/utils.js +95 -11
- package/core/objects/dictionary.js +43 -0
- package/core/objects/dictionaryManager.js +80 -0
- package/core/properties/dimType.js +117 -0
- package/core/properties/flags.js +66 -0
- package/core/properties/property.js +26 -0
- package/core/properties/propertyManager.js +65 -19
- package/core/tables/appId.js +31 -0
- package/core/tables/appIdManager.js +44 -0
- package/core/tables/block.js +323 -0
- package/core/tables/blockManager.js +48 -0
- package/core/tables/blockRecord.js +29 -0
- package/core/tables/blockRecordManager.js +37 -0
- package/core/tables/dimStyle.js +627 -0
- package/core/tables/dimStyleManager.js +187 -0
- package/core/tables/endblk.js +28 -0
- package/core/tables/layer.js +219 -0
- package/core/tables/layerManager.js +47 -0
- package/core/tables/ltype.js +85 -0
- package/core/tables/ltypeManager.js +65 -0
- package/core/tables/style.js +145 -0
- package/core/tables/styleManager.js +55 -0
- package/core/tables/styleManagerBase.js +110 -0
- package/core/tables/tableManagerBase.js +354 -0
- package/core/tables/ucs.js +28 -0
- package/core/tables/ucsManager.js +44 -0
- package/core/tables/view.js +28 -0
- package/core/tables/viewManager.js +44 -0
- package/core/tables/vport.js +70 -0
- package/core/tables/vportManager.js +65 -0
- package/core/tools/chamfer.js +343 -0
- package/core/tools/chamferFilletBase.js +162 -0
- package/core/tools/copy.js +68 -40
- package/core/tools/copybase.js +65 -0
- package/core/tools/copyclip.js +59 -0
- package/core/tools/cornerEntity.js +138 -0
- package/core/tools/cutclip.js +72 -0
- package/core/tools/distance.js +37 -9
- package/core/tools/erase.js +43 -13
- package/core/tools/explode.js +117 -0
- package/core/tools/extend.js +71 -32
- package/core/tools/fillet.js +336 -0
- package/core/tools/identify.js +33 -6
- package/core/tools/matchProp.js +106 -0
- package/core/tools/mirror.js +141 -0
- package/core/tools/move.js +65 -32
- package/core/tools/offset.js +321 -0
- package/core/tools/pan.js +54 -0
- package/core/tools/pasteclip.js +93 -0
- package/core/tools/purge.js +90 -0
- package/core/tools/rotate.js +105 -70
- package/core/tools/scale.js +166 -0
- package/core/tools/tool.js +14 -4
- package/core/tools/trim.js +71 -32
- package/core/tools/zoom.js +152 -0
- package/package.json +3 -305
- package/test/dimensions/alignedDimension.test.js +211 -0
- package/test/dimensions/angularDimension.test.js +243 -0
- package/test/dimensions/baseDimension.test.js +239 -0
- package/test/dimensions/diametricDimension.test.js +203 -0
- package/test/dimensions/dimension.test.js +102 -0
- package/test/dimensions/radialDimension.test.js +203 -0
- package/test/dimensions/rotatedDimension.test.js +224 -0
- package/test/entities/arc.test.js +463 -41
- package/test/entities/arctext.test.js +329 -0
- package/test/entities/basePolyline.test.js +459 -10
- package/test/entities/circle.test.js +312 -7
- package/test/entities/entity.test.js +28 -9
- package/test/entities/hatch.test.js +606 -0
- package/test/entities/insert.test.js +90 -0
- package/test/entities/line.test.js +182 -6
- package/test/entities/point.test.js +375 -37
- package/test/entities/solid.test.js +156 -0
- package/test/entities/text.test.js +533 -7
- package/test/integration/exportIntegration.reference.dxf +1706 -0
- package/test/integration/exportIntegration.test.js +186 -0
- package/test/integration/importExportIntegration.test.js +126 -0
- package/test/integration/intersectionIntegration.test.js +880 -0
- package/test/integration/userInputIntegration.reference.dxf +1410 -0
- package/test/integration/userInputIntegration.test.js +269 -0
- package/test/lib/boundingBox.test.js +26 -2
- package/test/lib/canvas.test.js +613 -5
- package/test/lib/clipboard.test.js +70 -0
- package/test/lib/colour.test.js +114 -0
- package/test/lib/colours.test.js +63 -18
- package/test/lib/commandLine.test.js +159 -22
- package/test/lib/commandManager.test.js +4 -4
- package/test/lib/constants.test.js +9 -0
- package/test/lib/dxf/dxfFile.test.js +6 -2
- package/test/lib/dxf/dxfIterator.test.js +1 -1
- package/test/lib/dxf/dxfWrite.test.js +173 -0
- package/test/lib/dxf/handleManager.test.js +137 -0
- package/test/lib/dxf/sections/blocks.test.js +5 -5
- package/test/lib/dxf/sections/entities.test.js +4 -4
- package/test/lib/dxf/sections/header.test.js +18 -4
- package/test/lib/dxf/sections/objects.test.js +132 -0
- package/test/lib/dxf/sections/section.test.js +29 -29
- package/test/lib/dxf/sections/tables.test.js +3 -3
- package/test/lib/entityManager.test.js +163 -0
- package/test/lib/headers.test.js +233 -0
- package/test/lib/inputManager.test.js +1144 -5
- package/test/lib/intersect.test.js +454 -331
- package/test/lib/logging.test.js +1 -1
- package/test/lib/matrix.test.js +1 -1
- package/test/lib/mouse.test.js +327 -4
- package/test/lib/patterns.test.js +105 -0
- package/test/lib/promptOptions.test.js +179 -0
- package/test/lib/scene.test.js +16 -52
- package/test/lib/selectionManager.test.js +17 -5
- package/test/lib/settings.test.js +111 -5
- package/test/lib/snapping.test.js +142 -4
- package/test/lib/stateManager.test.js +155 -0
- package/test/lib/utils.test.js +81 -1
- package/test/objects/dictionary.test.js +81 -0
- package/test/objects/dictionaryManager.test.js +34 -0
- package/test/properties/dimType.test.js +62 -0
- package/test/properties/flags.test.js +164 -0
- package/test/properties/property.test.js +13 -0
- package/test/properties/propertyManager.test.js +10 -11
- package/test/tables/appId.test.js +46 -0
- package/test/tables/appIdManager.test.js +72 -0
- package/test/tables/block.test.js +157 -0
- package/test/tables/blockManager.test.js +52 -0
- package/test/tables/blockRecord.test.js +39 -0
- package/test/tables/blockRecordManager.test.js +60 -0
- package/test/tables/dimstyle.test.js +72 -0
- package/test/tables/endblk.test.js +30 -0
- package/test/tables/layer.test.js +95 -0
- package/test/tables/layerManager.test.js +172 -0
- package/test/{styles → tables}/ltype.test.js +7 -7
- package/test/{styles → tables}/ltypeManager.test.js +2 -2
- package/test/tables/style.test.js +44 -0
- package/test/tables/stylemanagerbase.test.js +220 -0
- package/test/tables/tableManagerBase.test.js +194 -0
- package/test/tables/ucs.test.js +37 -0
- package/test/tables/ucsManager.test.js +48 -0
- package/test/tables/view.test.js +37 -0
- package/test/tables/viewManager.test.js +48 -0
- package/test/tables/vport.test.js +117 -0
- package/test/tables/vportManager.test.js +54 -0
- package/test/test-helpers/test-helpers.js +66 -0
- package/test/tools/chamfer.test.js +970 -0
- package/test/tools/chamferFilletBase.test.js +446 -0
- package/test/tools/copy.test.js +22 -14
- package/test/tools/copybase.test.js +93 -0
- package/test/tools/copyclip.test.js +92 -0
- package/test/tools/cornerEntity.test.js +201 -0
- package/test/tools/cutclip.test.js +94 -0
- package/test/tools/distance.test.js +140 -18
- package/test/tools/erase.test.js +12 -12
- package/test/tools/explode.test.js +45 -0
- package/test/tools/extend.test.js +326 -44
- package/test/tools/fillet.test.js +831 -0
- package/test/tools/identify.test.js +115 -16
- package/test/tools/matchProp.test.js +84 -0
- package/test/tools/mirror.test.js +475 -0
- package/test/tools/move.test.js +75 -19
- package/test/tools/offset.test.js +748 -0
- package/test/tools/pan.test.js +72 -0
- package/test/tools/pasteclip.test.js +100 -0
- package/test/tools/purge.test.js +89 -0
- package/test/tools/rotate.test.js +89 -23
- package/test/tools/scale.test.js +529 -0
- package/test/tools/trim.test.js +419 -84
- package/test/tools/zoom.test.js +504 -0
- package/core/entities/alignedDimension.js +0 -279
- package/core/entities/angularDimension.js +0 -194
- package/core/entities/baseDimension.js +0 -227
- package/core/entities/block.js +0 -247
- package/core/entities/diametricDimension.js +0 -133
- package/core/entities/dimension.js +0 -202
- package/core/entities/radialDimension.js +0 -126
- package/core/styles/dimStyle.js +0 -719
- package/core/styles/dimStyleManager.js +0 -47
- package/core/styles/layer.js +0 -133
- package/core/styles/layerManager.js +0 -40
- package/core/styles/ltype.js +0 -86
- package/core/styles/ltypeManager.js +0 -50
- package/core/styles/style.js +0 -158
- package/core/styles/styleManager.js +0 -43
- package/core/styles/styleManagerBase.js +0 -299
- package/test/entities/block.test.js +0 -22
- package/test/styles/dimstyle.test.js +0 -19
- package/test/styles/layerManager.test.js +0 -150
- package/test/styles/style.test.js +0 -33
- package/test/styles/stylemanagerbase.test.js +0 -219
|
@@ -1,287 +1,140 @@
|
|
|
1
|
-
import {Point} from '../../core/entities/point.js';
|
|
2
|
-
import {Intersection} from '../../core/lib/intersect';
|
|
1
|
+
import { Point } from '../../core/entities/point.js';
|
|
2
|
+
import { Intersection } from '../../core/lib/intersect';
|
|
3
3
|
|
|
4
4
|
test('Test Intersection.intersectCircleEllipse()', () => {
|
|
5
5
|
expect(true).toBeTruthy();
|
|
6
6
|
// TODO: intersectCircleEllipse
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
test('Test
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const result = Intersection.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// No Intersection - Outside
|
|
20
|
-
const circle1 = {centre: new Point(10, 10), radius: 2};
|
|
21
|
-
const line1 = {start: new Point(), end: new Point(0, 10)};
|
|
22
|
-
const result1 = Intersection.intersectCircleLine(circle1, line1, false);
|
|
23
|
-
expect(result1.status).toBe('Outside');
|
|
24
|
-
expect(result1.points.length).toBe(0);
|
|
25
|
-
|
|
26
|
-
// No Intersection - Inside
|
|
27
|
-
const circle2 = {centre: new Point(), radius: 20};
|
|
28
|
-
const line2 = {start: new Point(), end: new Point(0, 10)};
|
|
29
|
-
const result2 = Intersection.intersectCircleLine(circle2, line2, false);
|
|
30
|
-
expect(result2.status).toBe('Inside');
|
|
31
|
-
expect(result2.points.length).toBe(0);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test('Test Intersection.intersectLineCircle()', () => {
|
|
35
|
-
// Intersection
|
|
36
|
-
const circle = {centre: new Point(10, 10), radius: 5};
|
|
37
|
-
const line = {start: new Point(), end: new Point(10, 10)};
|
|
38
|
-
const result = Intersection.intersectLineCircle(line, circle, false);
|
|
39
|
-
expect(result.status).toBe('Intersection');
|
|
40
|
-
expect(result.points.length).toBe(1);
|
|
41
|
-
expect(result.points[0].x).toBeCloseTo(6.46);
|
|
42
|
-
expect(result.points[0].y).toBeCloseTo(6.46);
|
|
43
|
-
|
|
44
|
-
// No Intersection - Outside
|
|
45
|
-
const circle1 = {centre: new Point(10, 10), radius: 2};
|
|
46
|
-
const line1 = {start: new Point(), end: new Point(0, 10)};
|
|
47
|
-
const result1 = Intersection.intersectLineCircle(line1, circle1, false);
|
|
48
|
-
expect(result1.status).toBe('Outside');
|
|
49
|
-
expect(result1.points.length).toBe(0);
|
|
50
|
-
|
|
51
|
-
// No Intersection - Inside
|
|
52
|
-
const circle2 = {centre: new Point(), radius: 20};
|
|
53
|
-
const line2 = {start: new Point(), end: new Point(0, 10)};
|
|
54
|
-
const result2 = Intersection.intersectLineCircle(line2, circle2, false);
|
|
55
|
-
expect(result2.status).toBe('Inside');
|
|
56
|
-
expect(result2.points.length).toBe(0);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test('Test Intersection.intersectCircleCircle()', () => {
|
|
60
|
-
// Intersection
|
|
61
|
-
const circle1 = {centre: new Point(10, 10), radius: 5};
|
|
62
|
-
const circle2 = {centre: new Point(15, 10), radius: 5};
|
|
63
|
-
const result = Intersection.intersectCircleCircle(circle1, circle2, false);
|
|
64
|
-
expect(result.status).toBe('Intersection');
|
|
65
|
-
expect(result.points.length).toBe(2);
|
|
66
|
-
expect(result.points[0].x).toBeCloseTo(12.5);
|
|
67
|
-
expect(result.points[0].y).toBeCloseTo(14.33);
|
|
68
|
-
|
|
69
|
-
// No Intersection - Inside
|
|
70
|
-
const circle3 = {centre: new Point(10, 10), radius: 5};
|
|
71
|
-
const circle4 = {centre: new Point(10, 10), radius: 2};
|
|
72
|
-
const result1 = Intersection.intersectCircleCircle(circle3, circle4, false);
|
|
73
|
-
expect(result1.status).toBe('Inside');
|
|
74
|
-
expect(result1.points.length).toBe(0);
|
|
75
|
-
|
|
76
|
-
// No Intersection - Outside
|
|
77
|
-
const circle5 = {centre: new Point(10, 10), radius: 5};
|
|
78
|
-
const circle6 = {centre: new Point(-10, 10), radius: 2};
|
|
79
|
-
const result2 = Intersection.intersectCircleCircle(circle5, circle6, false);
|
|
80
|
-
expect(result2.status).toBe('Outside');
|
|
81
|
-
expect(result2.points.length).toBe(0);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test('Test Intersection.intersectCirclePolygon()', () => {
|
|
85
|
-
// Intersection.intersectCirclePolygon(c,r,points);
|
|
86
|
-
expect(true).toBeTruthy();
|
|
87
|
-
// TODO: intersectCirclePolygon
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test('Test Intersection.intersectArcRectangle()', () => {
|
|
91
|
-
// Intersection
|
|
92
|
-
const arc = {centre: new Point(), radius: 14.14, startPoint: new Point(10, 10), endPoint: new Point(-10, 10)};
|
|
93
|
-
const rectangle = {start: new Point(), end: new Point(25, 25)};
|
|
94
|
-
const result = Intersection.intersectArcRectangle(arc, rectangle, false);
|
|
9
|
+
test('Test intersectSegmentSegment - circle line', () => {
|
|
10
|
+
// CCW semicircular arc from (10,0) to (-10,0) with bulge=1
|
|
11
|
+
// centre (0,0), radius 10, passes through (0,10)
|
|
12
|
+
// Vertical line from (0,-15) to (0,15) crosses the arc at (0,10)
|
|
13
|
+
const result = Intersection.intersectSegmentSegment(
|
|
14
|
+
new Point(10, 0, 1), new Point(-10, 0),
|
|
15
|
+
new Point(0, -15), new Point(0, 15),
|
|
16
|
+
false,
|
|
17
|
+
);
|
|
95
18
|
expect(result.status).toBe('Intersection');
|
|
96
19
|
expect(result.points.length).toBe(1);
|
|
97
20
|
expect(result.points[0].x).toBeCloseTo(0);
|
|
98
|
-
expect(result.points[0].y).toBeCloseTo(
|
|
99
|
-
|
|
100
|
-
// No Intersection
|
|
101
|
-
const arc1 = {centre: new Point(), radius: 14.14, startPoint: new Point(-10, 0), endPoint: new Point(0, -10)};
|
|
102
|
-
const rectangle1 = {start: new Point(), end: new Point(25, 25)};
|
|
103
|
-
const result1 = Intersection.intersectArcRectangle(arc1, rectangle1, false);
|
|
104
|
-
expect(result1.status).toBe('No Intersection');
|
|
105
|
-
expect(result1.points.length).toBe(0);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
test('Test Intersection.intersectArcLine()', () => {
|
|
109
|
-
// Intersection
|
|
110
|
-
const arc = {centre: new Point(), radius: 14.14, startPoint: new Point(10, 10), endPoint: new Point(-10, 10)};
|
|
111
|
-
const line = {start: new Point(), end: new Point(0, 25)};
|
|
112
|
-
const result = Intersection.intersectArcLine(arc, line, false);
|
|
113
|
-
expect(result.status).toBe('Intersection');
|
|
114
|
-
expect(result.points.length).toBe(1);
|
|
115
|
-
expect(result.points[0].x).toBeCloseTo(0);
|
|
116
|
-
expect(result.points[0].y).toBeCloseTo(14.14);
|
|
117
|
-
|
|
118
|
-
// Intersection - Arc straddles 0 with startAngle > endAngle
|
|
119
|
-
const arc1 = {centre: new Point(), radius: 14.14, startPoint: new Point(10, -10), endPoint: new Point(-10, 10)};
|
|
120
|
-
const line1 = {start: new Point(), end: new Point(0, 25)};
|
|
121
|
-
const result1 = Intersection.intersectArcLine(arc1, line1, false);
|
|
122
|
-
expect(result1.status).toBe('Intersection');
|
|
123
|
-
expect(result1.points.length).toBe(1);
|
|
124
|
-
expect(result1.points[0].x).toBeCloseTo(0);
|
|
125
|
-
expect(result1.points[0].y).toBeCloseTo(14.14);
|
|
126
|
-
|
|
127
|
-
// No Intersection
|
|
128
|
-
const arc2 = {centre: new Point(), radius: 14.14, startPoint: new Point(-10, 0), endPoint: new Point(0, -10)};
|
|
129
|
-
const line2 = {start: new Point(), end: new Point(0, 25)};
|
|
130
|
-
const result2 = Intersection.intersectArcLine(arc2, line2, false);
|
|
131
|
-
expect(result2.status).toBe('No Intersection');
|
|
132
|
-
expect(result2.points.length).toBe(0);
|
|
21
|
+
expect(result.points[0].y).toBeCloseTo(10);
|
|
133
22
|
});
|
|
134
23
|
|
|
135
|
-
test('Test
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
24
|
+
test('Test intersectSegmentSegment - tangent arc line', () => {
|
|
25
|
+
// CCW semicircular arc from (10,0) to (-10,0), centre (0,0), radius 10
|
|
26
|
+
// Horizontal line y=10 is tangent to the top of the arc at (0,10)
|
|
27
|
+
const result = Intersection.intersectSegmentSegment(
|
|
28
|
+
new Point(10, 0, 1), new Point(-10, 0),
|
|
29
|
+
new Point(-15, 10), new Point(15, 10),
|
|
30
|
+
false,
|
|
31
|
+
);
|
|
32
|
+
expect(result.status).toBe('Tangent');
|
|
141
33
|
expect(result.points.length).toBe(1);
|
|
142
34
|
expect(result.points[0].x).toBeCloseTo(0);
|
|
143
|
-
expect(result.points[0].y).toBeCloseTo(
|
|
144
|
-
|
|
145
|
-
// No Intersection
|
|
146
|
-
const arc1 = {centre: new Point(), radius: 14.14, startPoint: new Point(-10, 0), endPoint: new Point(0, -10)};
|
|
147
|
-
const line1 = {start: new Point(), end: new Point(0, 25)};
|
|
148
|
-
const result1 = Intersection.intersectLineArc(line1, arc1, false);
|
|
149
|
-
expect(result1.status).toBe('No Intersection');
|
|
150
|
-
expect(result1.points.length).toBe(0);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
test('Test Intersection.intersectCircleArc()', () => {
|
|
154
|
-
// Intersection
|
|
155
|
-
const arc = {centre: new Point(), radius: 14.14, startPoint: new Point(10, 10), endPoint: new Point(-10, 10)};
|
|
156
|
-
const circle = {centre: new Point(10, 10), radius: 5};
|
|
157
|
-
const result = Intersection.intersectCircleArc(circle, arc, false);
|
|
158
|
-
expect(result.status).toBe('Intersection');
|
|
159
|
-
expect(result.points.length).toBe(1);
|
|
160
|
-
expect(result.points[0].x).toBeCloseTo(5.894);
|
|
161
|
-
expect(result.points[0].y).toBeCloseTo(12.853);
|
|
162
|
-
|
|
163
|
-
// No Intersection
|
|
164
|
-
const arc1 = {centre: new Point(), radius: 14.14, startPoint: new Point(-10, 0), endPoint: new Point(0, -10)};
|
|
165
|
-
const circle1 = {centre: new Point(10, 10), radius: 5};
|
|
166
|
-
const result1 = Intersection.intersectCircleArc(circle1, arc1, false);
|
|
167
|
-
expect(result1.status).toBe('No Intersection');
|
|
168
|
-
expect(result1.points.length).toBe(0);
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
test('Test Intersection.intersectArcCircle()', () => {
|
|
172
|
-
// Intersection
|
|
173
|
-
const arc = {centre: new Point(), radius: 14.14, startPoint: new Point(10, 10), endPoint: new Point(-10, 10)};
|
|
174
|
-
const circle = {centre: new Point(10, 10), radius: 5};
|
|
175
|
-
const result = Intersection.intersectArcCircle(arc, circle, false);
|
|
176
|
-
expect(result.status).toBe('Intersection');
|
|
177
|
-
expect(result.points.length).toBe(1);
|
|
178
|
-
expect(result.points[0].x).toBeCloseTo(5.894);
|
|
179
|
-
expect(result.points[0].y).toBeCloseTo(12.853);
|
|
180
|
-
|
|
181
|
-
// Clockwise Arc Intersection
|
|
182
|
-
const cwArc = {centre: new Point(), radius: 14.14, startPoint: new Point(10, 10), endPoint: new Point(-10, 10), direction: -1};
|
|
183
|
-
const cwResult = Intersection.intersectArcCircle(cwArc, circle, false);
|
|
184
|
-
expect(cwResult.status).toBe('Intersection');
|
|
185
|
-
expect(cwResult.points.length).toBe(1);
|
|
186
|
-
expect(cwResult.points[0].x).toBeCloseTo(12.853);
|
|
187
|
-
expect(cwResult.points[0].y).toBeCloseTo(5.894);
|
|
188
|
-
|
|
189
|
-
// No Intersection
|
|
190
|
-
const arc1 = {centre: new Point(), radius: 14.14, startPoint: new Point(-10, 0), endPoint: new Point(0, -10)};
|
|
191
|
-
const circle1 = {centre: new Point(10, 10), radius: 5};
|
|
192
|
-
const result1 = Intersection.intersectArcCircle(arc1, circle1, false);
|
|
193
|
-
expect(result1.status).toBe('No Intersection');
|
|
194
|
-
expect(result1.points.length).toBe(0);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
test('Test Intersection.intersectCircleRectangle()', () => {
|
|
198
|
-
// Intersection
|
|
199
|
-
const circle = {centre: new Point(), radius: 14.14};
|
|
200
|
-
const rectangle = {start: new Point(), end: new Point(25, 25)};
|
|
201
|
-
const result = Intersection.intersectCircleRectangle(circle, rectangle, false);
|
|
202
|
-
expect(result.status).toBe('Intersection');
|
|
203
|
-
expect(result.points.length).toBe(2);
|
|
204
|
-
expect(result.points[0].x).toBeCloseTo(14.14);
|
|
205
|
-
expect(result.points[0].y).toBeCloseTo(0);
|
|
206
|
-
|
|
207
|
-
// No Intersection - Outside
|
|
208
|
-
const circle1 = {centre: new Point(12.5, 12.5), radius: 10};
|
|
209
|
-
const rectangle1 = {start: new Point(), end: new Point(25, 25)};
|
|
210
|
-
const result1 = Intersection.intersectCircleRectangle(circle1, rectangle1, false);
|
|
211
|
-
expect(result1.status).toBe('Outside');
|
|
212
|
-
expect(result1.points.length).toBe(0);
|
|
213
|
-
|
|
214
|
-
// No Intersection - Inside
|
|
215
|
-
const circle2 = {centre: new Point(12.5, 12.5), radius: 100};
|
|
216
|
-
const rectangle2 = {start: new Point(), end: new Point(25, 25)};
|
|
217
|
-
const result2 = Intersection.intersectCircleRectangle(circle2, rectangle2, false);
|
|
218
|
-
expect(result2.status).toBe('Inside');
|
|
219
|
-
expect(result2.points.length).toBe(0);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
test('Test Intersection.intersectEllipseEllipse()', () => {
|
|
223
|
-
// Intersection.intersectEllipseEllipse(c1,rx1,ry1,c2,rx2,ry2);
|
|
224
|
-
expect(true).toBeTruthy();
|
|
225
|
-
// TODO: intersectEllipseEllipse
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
test('Test Intersection.intersectEllipseLine()', () => {
|
|
229
|
-
// Intersection.intersectEllipseLine(ellipse,line,extend);
|
|
230
|
-
expect(true).toBeTruthy();
|
|
231
|
-
// TODO: intersectEllipseLine
|
|
35
|
+
expect(result.points[0].y).toBeCloseTo(10);
|
|
232
36
|
});
|
|
233
37
|
|
|
234
|
-
test('Test
|
|
235
|
-
//
|
|
236
|
-
|
|
237
|
-
|
|
38
|
+
test('Test intersectSegmentSegment - concentric arcs same radius', () => {
|
|
39
|
+
// Two semicircular arcs with the same centre and radius
|
|
40
|
+
const result = Intersection.intersectSegmentSegment(
|
|
41
|
+
new Point(10, 0, 1), new Point(-10, 0),
|
|
42
|
+
new Point(0, 10, 1), new Point(0, -10),
|
|
43
|
+
false,
|
|
44
|
+
);
|
|
45
|
+
expect(result.status).toBe('Coincident');
|
|
46
|
+
expect(result.points.length).toBe(0);
|
|
238
47
|
});
|
|
239
48
|
|
|
240
|
-
test('Test
|
|
241
|
-
//
|
|
242
|
-
|
|
243
|
-
|
|
49
|
+
test('Test intersectSegmentSegment - concentric arcs different radius', () => {
|
|
50
|
+
// Two semicircular arcs with the same centre but different radii
|
|
51
|
+
const result = Intersection.intersectSegmentSegment(
|
|
52
|
+
new Point(10, 0, 1), new Point(-10, 0),
|
|
53
|
+
new Point(5, 0, 1), new Point(-5, 0),
|
|
54
|
+
false,
|
|
55
|
+
);
|
|
56
|
+
expect(result.status).toBe('Inside');
|
|
57
|
+
expect(result.points.length).toBe(0);
|
|
244
58
|
});
|
|
245
59
|
|
|
246
|
-
test('Test
|
|
247
|
-
//
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
60
|
+
test('Test intersectSegmentSegment - line line', () => {
|
|
61
|
+
// Crossing - segments cross in their interiors
|
|
62
|
+
const result = Intersection.intersectSegmentSegment(
|
|
63
|
+
new Point(), new Point(0, 10),
|
|
64
|
+
new Point(-5, 5), new Point(5, 5),
|
|
65
|
+
false,
|
|
66
|
+
);
|
|
67
|
+
expect(result.status).toBe('Perpendicular');
|
|
252
68
|
expect(result.points.length).toBe(1);
|
|
253
69
|
expect(result.points[0].x).toBeCloseTo(0);
|
|
254
70
|
expect(result.points[0].y).toBeCloseTo(5);
|
|
255
71
|
|
|
256
|
-
//
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
72
|
+
// Crossing - non-perpendicular crossing
|
|
73
|
+
const resultCross = Intersection.intersectSegmentSegment(
|
|
74
|
+
new Point(0, 0), new Point(10, 5),
|
|
75
|
+
new Point(0, 5), new Point(10, 0),
|
|
76
|
+
false,
|
|
77
|
+
);
|
|
78
|
+
expect(resultCross.status).toBe('Crossing');
|
|
79
|
+
|
|
80
|
+
// Crossing - Extend (perpendicular - vertical boundary, horizontal selected extended)
|
|
81
|
+
const result1 = Intersection.intersectSegmentSegment(
|
|
82
|
+
new Point(), new Point(0, 10),
|
|
83
|
+
new Point(1, 5), new Point(5, 5),
|
|
84
|
+
false, true,
|
|
85
|
+
);
|
|
86
|
+
expect(result1.status).toBe('Perpendicular');
|
|
260
87
|
expect(result1.points.length).toBe(1);
|
|
261
88
|
expect(result1.points[0].x).toBeCloseTo(0);
|
|
262
89
|
expect(result1.points[0].y).toBeCloseTo(5);
|
|
263
90
|
|
|
264
91
|
// No Intersection - Parallel
|
|
265
|
-
const
|
|
266
|
-
|
|
92
|
+
const result2 = Intersection.intersectSegmentSegment(
|
|
93
|
+
new Point(), new Point(0, 10),
|
|
94
|
+
new Point(1, 0), new Point(1, 10),
|
|
95
|
+
false,
|
|
96
|
+
);
|
|
267
97
|
expect(result2.status).toBe('Parallel');
|
|
268
98
|
expect(result2.points.length).toBe(0);
|
|
269
99
|
|
|
270
|
-
//
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
100
|
+
// Touching - endpoint of one segment lies on interior of the other
|
|
101
|
+
const result3 = Intersection.intersectSegmentSegment(
|
|
102
|
+
new Point(), new Point(0, 10),
|
|
103
|
+
new Point(0, 1), new Point(0, 8),
|
|
104
|
+
false,
|
|
105
|
+
);
|
|
106
|
+
expect(result3.status).toBe('Touching');
|
|
107
|
+
expect(result3.points.length).toBe(1);
|
|
108
|
+
|
|
109
|
+
// No Intersection - Collinear but disjoint (no overlap)
|
|
110
|
+
const result4 = Intersection.intersectSegmentSegment(
|
|
111
|
+
new Point(0, 0), new Point(0, 5),
|
|
112
|
+
new Point(0, 7), new Point(0, 10),
|
|
113
|
+
false,
|
|
114
|
+
);
|
|
115
|
+
expect(result4.status).toBe('None');
|
|
116
|
+
expect(result4.points.length).toBe(0);
|
|
117
|
+
|
|
118
|
+
// Endpoint - segments share an endpoint
|
|
119
|
+
const result5 = Intersection.intersectSegmentSegment(
|
|
120
|
+
new Point(0, 0), new Point(0, 10),
|
|
121
|
+
new Point(0, 10), new Point(10, 10),
|
|
122
|
+
false,
|
|
123
|
+
);
|
|
124
|
+
expect(result5.status).toBe('Endpoint');
|
|
125
|
+
expect(result5.points.length).toBe(1);
|
|
126
|
+
expect(result5.points[0].x).toBeCloseTo(0);
|
|
127
|
+
expect(result5.points[0].y).toBeCloseTo(10);
|
|
275
128
|
});
|
|
276
129
|
|
|
277
|
-
test('Test
|
|
130
|
+
test('Test intersectPolylinePolyline - polyline line', () => {
|
|
278
131
|
// Intersection
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
132
|
+
let points = [new Point(), new Point(0, 10)];
|
|
133
|
+
let polyline = points;
|
|
134
|
+
let line = [new Point(-10, 5), new Point(10, 5)];
|
|
282
135
|
|
|
283
136
|
// Test polyline with single segment
|
|
284
|
-
|
|
137
|
+
let result = Intersection.intersectPolylinePolyline(polyline, line, false);
|
|
285
138
|
expect(result.status).toBe('Intersection');
|
|
286
139
|
expect(result.points.length).toBe(1);
|
|
287
140
|
expect(result.points[0].x).toBeCloseTo(0);
|
|
@@ -289,26 +142,93 @@ test('Test Intersection.intersectPolylineLine()', () => {
|
|
|
289
142
|
|
|
290
143
|
// Test polyline with multiple segments
|
|
291
144
|
points.push(new Point(2, 10), new Point(2, 0));
|
|
292
|
-
|
|
293
|
-
expect(
|
|
294
|
-
expect(
|
|
295
|
-
expect(
|
|
296
|
-
expect(
|
|
145
|
+
result = Intersection.intersectPolylinePolyline(polyline, line, false);
|
|
146
|
+
expect(result.status).toBe('Intersection');
|
|
147
|
+
expect(result.points.length).toBe(2);
|
|
148
|
+
expect(result.points[1].x).toBeCloseTo(2);
|
|
149
|
+
expect(result.points[1].y).toBeCloseTo(5);
|
|
297
150
|
|
|
298
151
|
// No Intersection
|
|
299
|
-
const line2 =
|
|
300
|
-
|
|
301
|
-
expect(
|
|
302
|
-
expect(
|
|
152
|
+
const line2 = [new Point(5, 0), new Point(5, 10)];
|
|
153
|
+
result = Intersection.intersectPolylinePolyline(polyline, line2, false);
|
|
154
|
+
expect(result.status).toBe('None');
|
|
155
|
+
expect(result.points.length).toBe(0);
|
|
156
|
+
|
|
157
|
+
// Test polyline with 180 degree arc segment - 270 - 90 - negative bulge
|
|
158
|
+
// counter clockwise bulge = +ve, clockwise bulge = -ve,
|
|
159
|
+
points = [new Point(0, 0, -1), new Point(0, 10)];
|
|
160
|
+
polyline = points;
|
|
161
|
+
result = Intersection.intersectPolylinePolyline(polyline, line, false);
|
|
162
|
+
expect(result.status).toBe('Intersection');
|
|
163
|
+
expect(result.points.length).toBe(1);
|
|
164
|
+
expect(result.points[0].x).toBeCloseTo(-5);
|
|
165
|
+
expect(result.points[0].y).toBeCloseTo(5);
|
|
166
|
+
|
|
167
|
+
// Test polyline with 180 degree arc segment - 270 - 90 - positive bulge
|
|
168
|
+
// counter clockwise bulge = +ve, clockwise bulge = -ve,
|
|
169
|
+
points = [new Point(0, 0, 1), new Point(0, 10)];
|
|
170
|
+
polyline = points;
|
|
171
|
+
result = Intersection.intersectPolylinePolyline(polyline, line, false);
|
|
172
|
+
expect(result.status).toBe('Intersection');
|
|
173
|
+
expect(result.points.length).toBe(1);
|
|
174
|
+
expect(result.points[0].x).toBeCloseTo(5);
|
|
175
|
+
expect(result.points[0].y).toBeCloseTo(5);
|
|
176
|
+
|
|
177
|
+
// Test polyline with 180 degree arc segment 180 - 0 - negative bulge
|
|
178
|
+
// counter clockwise bulge = +ve, clockwise bulge = -ve,
|
|
179
|
+
points = [new Point(-5, 5, -1), new Point(5, 5)];
|
|
180
|
+
polyline = points;
|
|
181
|
+
line = [new Point(-10, 5), new Point(10, 5)];
|
|
182
|
+
result = Intersection.intersectPolylinePolyline(polyline, line, false);
|
|
183
|
+
expect(result.status).toBe('Intersection');
|
|
184
|
+
expect(result.points.length).toBe(2);
|
|
185
|
+
expect(result.points[0].x).toBeCloseTo(5);
|
|
186
|
+
expect(result.points[0].y).toBeCloseTo(5);
|
|
187
|
+
expect(result.points[1].x).toBeCloseTo(-5);
|
|
188
|
+
expect(result.points[1].y).toBeCloseTo(5);
|
|
189
|
+
|
|
190
|
+
// Test polyline with 180 degree arc segment 180 - 0 - positive bulge
|
|
191
|
+
// counter clockwise bulge = +ve, clockwise bulge = -ve,
|
|
192
|
+
points = [new Point(-5, 5, 1), new Point(5, 5)];
|
|
193
|
+
polyline = points;
|
|
194
|
+
line = [new Point(-10, 5), new Point(10, 5)];
|
|
195
|
+
result = Intersection.intersectPolylinePolyline(polyline, line, false);
|
|
196
|
+
expect(result.status).toBe('Intersection');
|
|
197
|
+
expect(result.points.length).toBe(2);
|
|
198
|
+
expect(result.points[0].x).toBeCloseTo(5);
|
|
199
|
+
expect(result.points[0].y).toBeCloseTo(5);
|
|
200
|
+
expect(result.points[1].x).toBeCloseTo(-5);
|
|
201
|
+
expect(result.points[1].y).toBeCloseTo(5);
|
|
202
|
+
|
|
203
|
+
// Test polyline with 180 degree arc segment 180 - 0 - negative bulge - offset line
|
|
204
|
+
// counter clockwise bulge = +ve, clockwise bulge = -ve
|
|
205
|
+
// direction: - ccw > 0, cw <= 0
|
|
206
|
+
points = [new Point(-5, 5, -1), new Point(5, 5)];
|
|
207
|
+
polyline = points;
|
|
208
|
+
line = [new Point(0, 7), new Point(10, 7)];
|
|
209
|
+
result = Intersection.intersectPolylinePolyline(polyline, line, false);
|
|
210
|
+
expect(result.status).toBe('Intersection');
|
|
211
|
+
expect(result.points.length).toBe(1);
|
|
212
|
+
expect(result.points[0].x).toBeCloseTo(4.5826);
|
|
213
|
+
expect(result.points[0].y).toBeCloseTo(7);
|
|
214
|
+
|
|
215
|
+
// Test polyline with 180 degree arc segment 180 - 0 - positive bulge - offset line
|
|
216
|
+
// counter clockwise bulge = +ve, clockwise bulge = -ve,
|
|
217
|
+
points = [new Point(-5, 5, 1), new Point(5, 5)];
|
|
218
|
+
polyline = points;
|
|
219
|
+
line = [new Point(0, 7), new Point(10, 7)];
|
|
220
|
+
result = Intersection.intersectPolylinePolyline(polyline, line, false);
|
|
221
|
+
expect(result.status).toBe('None');
|
|
222
|
+
expect(result.points.length).toBe(0);
|
|
303
223
|
});
|
|
304
224
|
|
|
305
|
-
test('Test
|
|
225
|
+
test('Test intersectPolylinePolyline with rectangle polyline', () => {
|
|
306
226
|
const points = [new Point(-5, 5), new Point(5, 5)];
|
|
307
|
-
const polyline =
|
|
308
|
-
const rectangle =
|
|
227
|
+
const polyline = points;
|
|
228
|
+
const rectangle = [new Point(), new Point(25, 0), new Point(25, 25), new Point(0, 25), new Point()];
|
|
309
229
|
|
|
310
230
|
// Test polyline with single segment
|
|
311
|
-
const result = Intersection.
|
|
231
|
+
const result = Intersection.intersectPolylinePolyline(polyline, rectangle, false);
|
|
312
232
|
expect(result.status).toBe('Intersection');
|
|
313
233
|
expect(result.points.length).toBe(1);
|
|
314
234
|
expect(result.points[0].x).toBeCloseTo(0);
|
|
@@ -316,103 +236,306 @@ test('Test Intersection.intersectPolylineRectangle()', () => {
|
|
|
316
236
|
|
|
317
237
|
// Test polyline with multiple segments
|
|
318
238
|
points.push(new Point(5, 20), new Point(30, 20));
|
|
319
|
-
const result2 = Intersection.
|
|
239
|
+
const result2 = Intersection.intersectPolylinePolyline(polyline, rectangle, false);
|
|
320
240
|
expect(result2.status).toBe('Intersection');
|
|
321
241
|
expect(result2.points.length).toBe(2);
|
|
322
|
-
expect(result2.points[0].x).toBeCloseTo(
|
|
323
|
-
expect(result2.points[0].y).toBeCloseTo(
|
|
242
|
+
expect(result2.points[0].x).toBeCloseTo(0);
|
|
243
|
+
expect(result2.points[0].y).toBeCloseTo(5);
|
|
244
|
+
expect(result2.points[1].x).toBeCloseTo(25);
|
|
245
|
+
expect(result2.points[1].y).toBeCloseTo(20);
|
|
324
246
|
|
|
325
|
-
//
|
|
247
|
+
// Overlapping collinear segments
|
|
326
248
|
const points2 = [new Point(5, 5), new Point(20, 20)];
|
|
327
|
-
const polyline2 =
|
|
328
|
-
const result3 = Intersection.
|
|
329
|
-
expect(result3.status).toBe('
|
|
330
|
-
expect(result3.points.length).toBe(
|
|
249
|
+
const polyline2 = points2;
|
|
250
|
+
const result3 = Intersection.intersectPolylinePolyline(polyline2, [new Point(), new Point(25, 25)], false);
|
|
251
|
+
expect(result3.status).toBe('Intersection');
|
|
252
|
+
expect(result3.points.length).toBe(1);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test('Test intersectPolylinePolyline - polyline arc', () => {
|
|
256
|
+
// Intersection - polyline(boundary) vs arc segment(selected)
|
|
257
|
+
const polyline = [new Point(), new Point(0, 25)];
|
|
258
|
+
// Arc segment from (10,10) to (-10,10) with bulge=1
|
|
259
|
+
// This creates a CCW semicircular arc with centre (0,10), radius 10
|
|
260
|
+
const arcPolyline = [new Point(10, 10, 1), new Point(-10, 10)];
|
|
261
|
+
const result = Intersection.intersectPolylinePolyline(polyline, arcPolyline, false);
|
|
262
|
+
expect(result.status).toBe('Intersection');
|
|
263
|
+
expect(result.points.length).toBe(1);
|
|
264
|
+
expect(result.points[0].x).toBeCloseTo(0);
|
|
265
|
+
expect(result.points[0].y).toBeCloseTo(20);
|
|
331
266
|
});
|
|
332
267
|
|
|
333
|
-
test('Test Intersection.
|
|
334
|
-
|
|
335
|
-
const
|
|
268
|
+
test('Test Intersection.intersectPolylinePolyline()', () => {
|
|
269
|
+
// Two crossing polylines with line segments
|
|
270
|
+
const polyline1 = [new Point(-10, 0), new Point(10, 0)];
|
|
271
|
+
const polyline2 = [new Point(0, -10), new Point(0, 10)];
|
|
336
272
|
|
|
337
|
-
|
|
338
|
-
const result = Intersection.intersectLineRectangle(line1, rectangle, false);
|
|
273
|
+
const result = Intersection.intersectPolylinePolyline(polyline1, polyline2, false);
|
|
339
274
|
expect(result.status).toBe('Intersection');
|
|
340
275
|
expect(result.points.length).toBe(1);
|
|
341
276
|
expect(result.points[0].x).toBeCloseTo(0);
|
|
342
|
-
expect(result.points[0].y).toBeCloseTo(
|
|
277
|
+
expect(result.points[0].y).toBeCloseTo(0);
|
|
343
278
|
|
|
344
|
-
//
|
|
345
|
-
const
|
|
346
|
-
const result2 = Intersection.
|
|
347
|
-
expect(result2.status).toBe('
|
|
348
|
-
expect(result2.points.length).toBe(
|
|
349
|
-
expect(result2.points[0].x).toBeCloseTo(25);
|
|
350
|
-
expect(result2.points[0].y).toBeCloseTo(17.857);
|
|
351
|
-
expect(result2.points[1].x).toBeCloseTo(0);
|
|
352
|
-
expect(result2.points[1].y).toBeCloseTo(7.14);
|
|
279
|
+
// No intersection
|
|
280
|
+
const polyline3 = [new Point(20, 0), new Point(30, 0)];
|
|
281
|
+
const result2 = Intersection.intersectPolylinePolyline(polyline1, polyline3, false);
|
|
282
|
+
expect(result2.status).toBe('None');
|
|
283
|
+
expect(result2.points.length).toBe(0);
|
|
353
284
|
|
|
354
|
-
//
|
|
355
|
-
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
285
|
+
// Polyline with arc segment intersecting a line-segment polyline
|
|
286
|
+
// CCW arc from (-5,0) to (5,0) with bulge=1 goes through (0,-5)
|
|
287
|
+
const polyline4 = [new Point(-5, 0, 1), new Point(5, 0)];
|
|
288
|
+
const polyline5 = [new Point(0, -10), new Point(0, -3)];
|
|
289
|
+
|
|
290
|
+
const result3 = Intersection.intersectPolylinePolyline(polyline4, polyline5, false);
|
|
291
|
+
expect(result3.status).toBe('Intersection');
|
|
292
|
+
expect(result3.points.length).toBe(1);
|
|
293
|
+
expect(result3.points[0].x).toBeCloseTo(0);
|
|
294
|
+
expect(result3.points[0].y).toBeCloseTo(-5);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test('Test intersectPolylinePolyline - polyline arc with extend', () => {
|
|
298
|
+
// Arc: quarter circle from (10,0) to (0,10) centred at origin, radius 10, CCW
|
|
299
|
+
// Represent as polyline with arc segment
|
|
300
|
+
const arcPolyline = [new Point(10, 0, 1), new Point(0, 10)];
|
|
301
|
+
|
|
302
|
+
// Polyline crossing the arc
|
|
303
|
+
const polyline = [new Point(0, 0), new Point(15, 15)];
|
|
304
|
+
|
|
305
|
+
// Without extend - intersection should be on the arc
|
|
306
|
+
const result1 = Intersection.intersectPolylinePolyline(polyline, arcPolyline, false);
|
|
307
|
+
expect(result1.status).toBe('Intersection');
|
|
308
|
+
expect(result1.points.length).toBe(1);
|
|
309
|
+
|
|
310
|
+
// With extend - all circle intersections returned (not filtered by arc bounds)
|
|
311
|
+
const result2 = Intersection.intersectPolylinePolyline(polyline, arcPolyline, true);
|
|
312
|
+
expect(result2.status).toBe('Intersection');
|
|
313
|
+
expect(result2.points.length).toBeGreaterThanOrEqual(1);
|
|
359
314
|
});
|
|
360
315
|
|
|
361
|
-
test('Test
|
|
362
|
-
|
|
363
|
-
const
|
|
316
|
+
test('Test intersectSegmentSegment - both segments extended (ray-ray equivalent)', () => {
|
|
317
|
+
// Perpendicular lines meeting at origin
|
|
318
|
+
const r1 = Intersection.intersectSegmentSegment(
|
|
319
|
+
new Point(-5, 0), new Point(5, 0),
|
|
320
|
+
new Point(0, -5), new Point(0, 5),
|
|
321
|
+
true, true,
|
|
322
|
+
);
|
|
323
|
+
expect(r1.points.length).toBe(1);
|
|
324
|
+
expect(r1.points[0].x).toBeCloseTo(0);
|
|
325
|
+
expect(r1.points[0].y).toBeCloseTo(0);
|
|
326
|
+
|
|
327
|
+
// Non-perpendicular: lines y=1 and x=1 meeting at (1, 1)
|
|
328
|
+
const r2 = Intersection.intersectSegmentSegment(
|
|
329
|
+
new Point(0, 1), new Point(10, 1),
|
|
330
|
+
new Point(1, 0), new Point(1, 10),
|
|
331
|
+
true, true,
|
|
332
|
+
);
|
|
333
|
+
expect(r2.points.length).toBe(1);
|
|
334
|
+
expect(r2.points[0].x).toBeCloseTo(1);
|
|
335
|
+
expect(r2.points[0].y).toBeCloseTo(1);
|
|
336
|
+
|
|
337
|
+
// 45-degree lines crossing at (5, 5)
|
|
338
|
+
const r3 = Intersection.intersectSegmentSegment(
|
|
339
|
+
new Point(0, 0), new Point(10, 10),
|
|
340
|
+
new Point(10, 0), new Point(0, 10),
|
|
341
|
+
true, true,
|
|
342
|
+
);
|
|
343
|
+
expect(r3.points.length).toBe(1);
|
|
344
|
+
expect(r3.points[0].x).toBeCloseTo(5);
|
|
345
|
+
expect(r3.points[0].y).toBeCloseTo(5);
|
|
346
|
+
|
|
347
|
+
// Parallel lines — should return no points
|
|
348
|
+
const r4 = Intersection.intersectSegmentSegment(
|
|
349
|
+
new Point(0, 0), new Point(10, 0),
|
|
350
|
+
new Point(0, 1), new Point(10, 1),
|
|
351
|
+
true, true,
|
|
352
|
+
);
|
|
353
|
+
expect(r4.points.length).toBe(0);
|
|
354
|
+
|
|
355
|
+
// Disjoint segments that only intersect when both extended
|
|
356
|
+
const r5 = Intersection.intersectSegmentSegment(
|
|
357
|
+
new Point(0, 0), new Point(2, 0),
|
|
358
|
+
new Point(5, -2), new Point(5, -1),
|
|
359
|
+
true, true,
|
|
360
|
+
);
|
|
361
|
+
expect(r5.points.length).toBe(1);
|
|
362
|
+
expect(r5.points[0].x).toBeCloseTo(5);
|
|
363
|
+
expect(r5.points[0].y).toBeCloseTo(0);
|
|
364
|
+
});
|
|
364
365
|
|
|
365
|
-
|
|
366
|
-
|
|
366
|
+
// ------------------------------------------------------------
|
|
367
|
+
// intersectSegmentSegment — circle/arc vs line, non-origin centre
|
|
368
|
+
// These tests specifically exercise the numerical stability fix:
|
|
369
|
+
// computing centreToStart = a1 - c before squaring avoids
|
|
370
|
+
// floating-point cancellation that occurs when the expanded form
|
|
371
|
+
// a1² + c² - 2·a1·c is used with an off-origin circle centre.
|
|
372
|
+
// ------------------------------------------------------------
|
|
373
|
+
|
|
374
|
+
test('intersectSegmentSegment - arc vs line, non-origin centre, two circle intersections but one on arc', () => {
|
|
375
|
+
// Circle centred at (1000, 1000), radius 50.
|
|
376
|
+
// Top point: (1000, 1050), bottom: (1000, 950).
|
|
377
|
+
// Left semicircle arc: top → bottom with bulge=1 (CCW).
|
|
378
|
+
// Horizontal line through centre: (950, 1000) → (1050, 1000).
|
|
379
|
+
// The full circle intersects the line at (950,1000) and (1050,1000),
|
|
380
|
+
// but only (950,1000) lies on the left semicircle arc — the arc filter
|
|
381
|
+
// removes the right-side point, leaving one result.
|
|
382
|
+
const leftArcStart = new Point(1000, 1050, 1);
|
|
383
|
+
const leftArcEnd = new Point(1000, 950);
|
|
384
|
+
|
|
385
|
+
const lineStart = new Point(950, 1000);
|
|
386
|
+
const lineEnd = new Point(1050, 1000);
|
|
387
|
+
|
|
388
|
+
// arc(boundary) vs line(selected)
|
|
389
|
+
const result = Intersection.intersectSegmentSegment(
|
|
390
|
+
leftArcStart, leftArcEnd,
|
|
391
|
+
lineStart, lineEnd,
|
|
392
|
+
false,
|
|
393
|
+
);
|
|
394
|
+
// Only the point on the left semicircle passes the arc filter
|
|
367
395
|
expect(result.status).toBe('Intersection');
|
|
368
396
|
expect(result.points.length).toBe(1);
|
|
369
|
-
expect(result.points[0].x).toBeCloseTo(
|
|
370
|
-
expect(result.points[0].y).toBeCloseTo(
|
|
397
|
+
expect(result.points[0].x).toBeCloseTo(950);
|
|
398
|
+
expect(result.points[0].y).toBeCloseTo(1000);
|
|
399
|
+
});
|
|
371
400
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
401
|
+
test('intersectSegmentSegment - arc vs line, non-origin centre, line outside arc', () => {
|
|
402
|
+
// Same circle at (1000, 1000) radius 50.
|
|
403
|
+
// Line entirely to the right of centre: (1060, 900) → (1060, 1100).
|
|
404
|
+
// This line is outside the circle entirely.
|
|
405
|
+
const arcStart = new Point(1000, 1050, 1);
|
|
406
|
+
const arcEnd = new Point(1000, 950);
|
|
407
|
+
|
|
408
|
+
const result = Intersection.intersectSegmentSegment(
|
|
409
|
+
arcStart, arcEnd,
|
|
410
|
+
new Point(1060, 900), new Point(1060, 1100),
|
|
411
|
+
false,
|
|
412
|
+
);
|
|
413
|
+
expect(result.status).toBe('Outside');
|
|
414
|
+
expect(result.points.length).toBe(0);
|
|
415
|
+
});
|
|
381
416
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
417
|
+
test('intersectSegmentSegment - arc vs line, non-origin centre, line inside circle', () => {
|
|
418
|
+
// Same circle at (1000, 1000) radius 50.
|
|
419
|
+
// Short line fully inside the circle: (1000, 990) → (1000, 1010).
|
|
420
|
+
// The circle-line quadratic yields two roots outside [0,1];
|
|
421
|
+
// one u<0 and one u>1 → INSIDE status, no points without extend.
|
|
422
|
+
const arcStart = new Point(1000, 1050, 1);
|
|
423
|
+
const arcEnd = new Point(1000, 950);
|
|
424
|
+
|
|
425
|
+
const result = Intersection.intersectSegmentSegment(
|
|
426
|
+
arcStart, arcEnd,
|
|
427
|
+
new Point(1000, 990), new Point(1000, 1010),
|
|
428
|
+
false,
|
|
429
|
+
);
|
|
430
|
+
expect(result.status).toBe('Inside');
|
|
431
|
+
expect(result.points.length).toBe(0);
|
|
387
432
|
});
|
|
388
433
|
|
|
389
|
-
test('
|
|
390
|
-
//
|
|
391
|
-
|
|
392
|
-
//
|
|
434
|
+
test('intersectPolylinePolyline - full circle vs diameter line, non-origin centre', () => {
|
|
435
|
+
// Reproduces the real-world trim failure:
|
|
436
|
+
// Circle centred at (588.75, 354.25), radius 78.136.
|
|
437
|
+
// The line connecting the two points where it intersects the
|
|
438
|
+
// circle is a near-diameter, with large absolute coordinates.
|
|
439
|
+
// Prior to the fix the discriminant underflowed to 0 or negative
|
|
440
|
+
// due to floating-point cancellation, returning no intersections.
|
|
441
|
+
const cx = 588.7494381894326;
|
|
442
|
+
const cy = 354.25057706935644;
|
|
443
|
+
const r = 78.13609384123743;
|
|
444
|
+
|
|
445
|
+
// Circle represented as two CCW semicircular arc segments (matching
|
|
446
|
+
// Circle.toPolylinePoints() output):
|
|
447
|
+
// top = centre.project(0, r) → (cx, cy + r)
|
|
448
|
+
// bot = centre.project(0, -r) → (cx, cy - r)
|
|
449
|
+
const top = new Point(cx, cy + r, 1); // left semicircle start
|
|
450
|
+
const bot = new Point(cx, cy - r, 1); // right semicircle start
|
|
451
|
+
const topClose = new Point(cx, cy + r); // closure point
|
|
452
|
+
|
|
453
|
+
const circlePolyline = [top, bot, topClose];
|
|
454
|
+
|
|
455
|
+
// The failing line from the DXF file — a near-diameter of the circle.
|
|
456
|
+
const linePolyline = [
|
|
457
|
+
new Point(644, 299.00001525878906),
|
|
458
|
+
new Point(533.4988763788651, 409.5011388799238),
|
|
459
|
+
];
|
|
460
|
+
|
|
461
|
+
const result = Intersection.intersectPolylinePolyline(linePolyline, circlePolyline, false);
|
|
462
|
+
expect(result.status).toBe('Intersection');
|
|
463
|
+
// The line passes through both halves of the circle, yielding two points.
|
|
464
|
+
expect(result.points.length).toBe(2);
|
|
465
|
+
// Each intersection point must lie approximately on the circle.
|
|
466
|
+
for (const pt of result.points) {
|
|
467
|
+
const dist = Math.sqrt((pt.x - cx) ** 2 + (pt.y - cy) ** 2);
|
|
468
|
+
expect(dist).toBeCloseTo(r, 3);
|
|
469
|
+
}
|
|
393
470
|
});
|
|
394
471
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
472
|
+
// ------------------------------------------------------------
|
|
473
|
+
// intersectCircleCircle — covering the INTERSECTION and OUTSIDE
|
|
474
|
+
// branches of #intersectCircleCircle, including the refactored
|
|
475
|
+
// axialDist / halfChordLength / chordMidpoint / perpOffset logic.
|
|
476
|
+
// ------------------------------------------------------------
|
|
477
|
+
|
|
478
|
+
test('intersectSegmentSegment - arc vs arc, two intersecting circles, single shared point per arc pair', () => {
|
|
479
|
+
// Circle 1: centre (0,0), radius 5 — top CCW semicircle: (5,0) → (-5,0)
|
|
480
|
+
// Circle 2: centre (6,0), radius 5 — top CCW semicircle: (11,0) → (1,0)
|
|
481
|
+
// The two circles intersect at (3,4) and (3,-4).
|
|
482
|
+
// Both top arcs contain (3,4); neither contains (3,-4).
|
|
483
|
+
const result = Intersection.intersectSegmentSegment(
|
|
484
|
+
new Point(5, 0, 1), new Point(-5, 0),
|
|
485
|
+
new Point(11, 0, 1), new Point(1, 0),
|
|
486
|
+
false,
|
|
487
|
+
);
|
|
488
|
+
expect(result.status).toBe('Intersection');
|
|
489
|
+
expect(result.points.length).toBe(1);
|
|
490
|
+
expect(result.points[0].x).toBeCloseTo(3);
|
|
491
|
+
expect(result.points[0].y).toBeCloseTo(4);
|
|
399
492
|
});
|
|
400
493
|
|
|
401
|
-
test('
|
|
402
|
-
|
|
403
|
-
|
|
494
|
+
test('intersectSegmentSegment - arc vs arc, circles outside each other', () => {
|
|
495
|
+
// Circle 1: centre (0,0), radius 5 — top arc: (5,0) → (-5,0)
|
|
496
|
+
// Circle 2: centre (20,0), radius 5 — top arc: (25,0) → (15,0)
|
|
497
|
+
// cDist (20) > rMax (10): OUTSIDE, no intersection points.
|
|
498
|
+
const result = Intersection.intersectSegmentSegment(
|
|
499
|
+
new Point(5, 0, 1), new Point(-5, 0),
|
|
500
|
+
new Point(25, 0, 1), new Point(15, 0),
|
|
501
|
+
false,
|
|
502
|
+
);
|
|
503
|
+
expect(result.status).toBe('Outside');
|
|
504
|
+
expect(result.points.length).toBe(0);
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
test('intersectPolylinePolyline - two full circles (two arcs each) intersecting at two points', () => {
|
|
508
|
+
// Circle 1: centre (0,0), radius 5.
|
|
509
|
+
// Circle 2: centre (6,0), radius 5.
|
|
510
|
+
// Intersection points: (3,4) and (3,-4).
|
|
511
|
+
// Each circle is represented as two CCW semicircular arc segments.
|
|
512
|
+
const circle1 = [new Point(5, 0, 1), new Point(-5, 0, 1), new Point(5, 0)];
|
|
513
|
+
const circle2 = [new Point(11, 0, 1), new Point(1, 0, 1), new Point(11, 0)];
|
|
404
514
|
|
|
405
|
-
const result = Intersection.
|
|
515
|
+
const result = Intersection.intersectPolylinePolyline(circle1, circle2, false);
|
|
406
516
|
expect(result.status).toBe('Intersection');
|
|
407
517
|
expect(result.points.length).toBe(2);
|
|
408
|
-
expect(result.points[0].x).toBeCloseTo(25);
|
|
409
|
-
expect(result.points[0].y).toBeCloseTo(10);
|
|
410
|
-
expect(result.points[1].x).toBeCloseTo(10);
|
|
411
|
-
expect(result.points[1].y).toBeCloseTo(25);
|
|
412
518
|
|
|
413
|
-
//
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
519
|
+
// Both points must lie on both circles (radius 5 from each centre).
|
|
520
|
+
for (const pt of result.points) {
|
|
521
|
+
expect(Math.sqrt(pt.x ** 2 + pt.y ** 2)).toBeCloseTo(5);
|
|
522
|
+
expect(Math.sqrt((pt.x - 6) ** 2 + pt.y ** 2)).toBeCloseTo(5);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Verify the specific coordinate values.
|
|
526
|
+
const ys = result.points.map((p) => p.y).sort((a, b) => a - b);
|
|
527
|
+
expect(ys[0]).toBeCloseTo(-4);
|
|
528
|
+
expect(ys[1]).toBeCloseTo(4);
|
|
529
|
+
result.points.forEach((p) => expect(p.x).toBeCloseTo(3));
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
test('intersectPolylinePolyline - two full circles outside each other, no intersection', () => {
|
|
533
|
+
// Circle 1: centre (0,0), radius 5.
|
|
534
|
+
// Circle 2: centre (20,0), radius 5. cDist=20 > rMax=10.
|
|
535
|
+
const circle1 = [new Point(5, 0, 1), new Point(-5, 0, 1), new Point(5, 0)];
|
|
536
|
+
const circle2 = [new Point(25, 0, 1), new Point(15, 0, 1), new Point(25, 0)];
|
|
537
|
+
|
|
538
|
+
const result = Intersection.intersectPolylinePolyline(circle1, circle2, false);
|
|
539
|
+
expect(result.status).toBe('None');
|
|
540
|
+
expect(result.points.length).toBe(0);
|
|
418
541
|
});
|