Returns:
diff --git a/docs/Box.html b/docs/Box.html index c942712..987460f 100644 --- a/docs/Box.html +++ b/docs/Box.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/Circle.html b/docs/Circle.html index 6a43af9..6b6835e 100644 --- a/docs/Circle.html +++ b/docs/Circle.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/CircularLinkedList.html b/docs/CircularLinkedList.html index d3ffeaa..075c982 100644 --- a/docs/CircularLinkedList.html +++ b/docs/CircularLinkedList.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/DE9IM.html b/docs/DE9IM.html index dc20a31..fa42518 100644 --- a/docs/DE9IM.html +++ b/docs/DE9IM.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/Edge.html b/docs/Edge.html index 7918238..f0b5291 100644 --- a/docs/Edge.html +++ b/docs/Edge.html @@ -24,7 +24,7 @@
containsSource:
@@ -1328,7 +1328,7 @@ middleSource:
@@ -1432,7 +1432,7 @@ pointAtL
Source:
@@ -1589,7 +1589,7 @@ setInclus
Source:
@@ -1720,7 +1720,7 @@ setOverlap<
Source:
@@ -1819,7 +1819,7 @@ Parameters:
diff --git a/docs/Errors.html b/docs/Errors.html
index c6bde70..e68d0b8 100644
--- a/docs/Errors.html
+++ b/docs/Errors.html
@@ -24,7 +24,7 @@
@@ -426,7 +426,7 @@ (static)
diff --git a/docs/Face.html b/docs/Face.html
index bb2a134..4b59c72 100644
--- a/docs/Face.html
+++ b/docs/Face.html
@@ -24,7 +24,7 @@
@@ -2343,7 +2343,7 @@ Returns:
diff --git a/docs/Inversion.html b/docs/Inversion.html
index 216d2b8..178b7a6 100644
--- a/docs/Inversion.html
+++ b/docs/Inversion.html
@@ -24,7 +24,7 @@
@@ -232,7 +232,7 @@ Classes
diff --git a/docs/Line.html b/docs/Line.html
index 24726c2..619ba6d 100644
--- a/docs/Line.html
+++ b/docs/Line.html
@@ -24,7 +24,7 @@
@@ -2629,7 +2629,7 @@ Returns:
diff --git a/docs/LinkedList.html b/docs/LinkedList.html
index 3d7e479..225d056 100644
--- a/docs/LinkedList.html
+++ b/docs/LinkedList.html
@@ -24,7 +24,7 @@
@@ -1094,7 +1094,7 @@ Returns:
diff --git a/docs/Matrix.html b/docs/Matrix.html
index 7ee2584..e031435 100644
--- a/docs/Matrix.html
+++ b/docs/Matrix.html
@@ -24,7 +24,7 @@
@@ -1613,7 +1613,7 @@ Returns:
diff --git a/docs/Multiline.html b/docs/Multiline.html
index aec92f0..cb2fe08 100644
--- a/docs/Multiline.html
+++ b/docs/Multiline.html
@@ -24,7 +24,7 @@
@@ -100,7 +100,7 @@ new Multilin
Source:
@@ -202,7 +202,7 @@ boxSource:
@@ -266,7 +266,7 @@ edgesSource:
@@ -330,7 +330,7 @@ verticesSource:
@@ -404,7 +404,7 @@ addVertexSource:
@@ -586,7 +586,7 @@ cloneSource:
@@ -690,7 +690,7 @@ findEd
Source:
@@ -848,7 +848,7 @@ rotateSource:
@@ -993,6 +993,90 @@ Returns:
+
+
+
+
+
+
+
+
+
+
+ setArcLength()
+
+
+
+
+
+
+ Set arc_length property for each of the edges in the face.
+Arc_length of the edge it the arc length from the first edge of the face
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1046,7 +1130,7 @@ splitSource:
@@ -1202,7 +1286,7 @@ svgSource:
@@ -1355,7 +1439,7 @@ toJSONSource:
@@ -1459,7 +1543,7 @@ toShapesSource:
@@ -1564,7 +1648,7 @@ transformSource:
@@ -1724,7 +1808,7 @@ translateSource:
@@ -1849,7 +1933,7 @@ Returns:
diff --git a/docs/PlanarSet.html b/docs/PlanarSet.html
index 50db807..b55e198 100644
--- a/docs/PlanarSet.html
+++ b/docs/PlanarSet.html
@@ -24,7 +24,7 @@
@@ -1053,7 +1053,7 @@ Returns:
diff --git a/docs/Point.html b/docs/Point.html
index e5ee07d..10df256 100644
--- a/docs/Point.html
+++ b/docs/Point.html
@@ -24,7 +24,7 @@
@@ -1861,7 +1861,7 @@ Returns:
diff --git a/docs/Polygon.html b/docs/Polygon.html
index ba93408..ffbd128 100644
--- a/docs/Polygon.html
+++ b/docs/Polygon.html
@@ -24,7 +24,7 @@
@@ -1129,7 +1129,7 @@ containsSource:
@@ -1242,16 +1242,14 @@ Returns:
- cut(multiline) → {Array.<Polygon>}
+ cut(multiline) → {Polygon}
- Cut polygon with multiline and return array of new polygons
-Multiline should be constructed from a line with intersection point, see notebook:
-https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ Cut polygon with multiline and return a new polygon
@@ -1287,7 +1285,7 @@ cutSource:
@@ -1381,190 +1379,7 @@ Returns:
-Array.<Polygon>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cutFace(pt1, pt2) → {Array.<Polygon>}
-
-
-
-
-
-
- Cut face of polygon with a segment between two points and create two new polygons
-Supposed that a segments between points does not intersect any other edge
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - Source:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameters:
-
-
-
-
-
-
- Name
-
-
- Type
-
-
-
-
-
- Description
-
-
-
-
-
-
-
-
- pt1
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pt2
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Returns:
-
-
-
-
- -
- Type:
-
- -
-
-
Array.<Polygon>
+Polygon
@@ -1590,7 +1405,8 @@ cutWithLin
- Return a result of cutting polygon with line
+ A special case of cut() function
+The return is a polygon cut with line
@@ -1626,7 +1442,7 @@ cutWithLin
- Source:
@@ -1942,7 +1758,7 @@ distanceTo<
- Source:
@@ -2102,7 +1918,7 @@ findEd
- Source:
@@ -2258,7 +2074,7 @@ intersectSource:
@@ -3026,7 +2842,7 @@ reverseSource:
@@ -3132,7 +2948,7 @@ rotateSource:
@@ -3330,7 +3146,7 @@ scaleSource:
@@ -3476,8 +3292,8 @@ splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
- Source:
@@ -3617,7 +3433,7 @@ svgSource:
@@ -3768,7 +3584,7 @@ toArraySource:
@@ -3873,7 +3689,7 @@ toJSONSource:
@@ -3977,7 +3793,7 @@ transformSource:
@@ -4137,7 +3953,7 @@ translateSource:
@@ -4262,7 +4078,7 @@ Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
@@ -288,7 +288,7 @@ boxSource:
@@ -352,7 +352,7 @@ endSource:
@@ -416,7 +416,7 @@ lengthSource:
@@ -480,7 +480,7 @@ slopeSource:
@@ -544,7 +544,7 @@ startSource:
@@ -618,7 +618,7 @@ cloneSource:
@@ -722,7 +722,7 @@ containsSource:
@@ -828,6 +828,165 @@ Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+ -
+ classes/ray.js, line 123
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+ -
+ Type:
+
+ -
+
+
number
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
@@ -1038,7 +1197,7 @@ rotateSource:
@@ -1199,7 +1358,7 @@ splitSource:
@@ -1347,7 +1506,7 @@ svgSource:
@@ -1508,7 +1667,7 @@ transformSource:
@@ -1633,7 +1792,7 @@ Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
- Source:
@@ -964,7 +964,7 @@ (constant) pol
- Source:
@@ -2466,7 +2466,7 @@ Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
pointAtL
Source:
@@ -1589,7 +1589,7 @@ setInclus
Source:
@@ -1720,7 +1720,7 @@ setOverlap<
Source:
@@ -1819,7 +1819,7 @@ Parameters:
diff --git a/docs/Errors.html b/docs/Errors.html
index c6bde70..e68d0b8 100644
--- a/docs/Errors.html
+++ b/docs/Errors.html
@@ -24,7 +24,7 @@
@@ -426,7 +426,7 @@ (static)
diff --git a/docs/Face.html b/docs/Face.html
index bb2a134..4b59c72 100644
--- a/docs/Face.html
+++ b/docs/Face.html
@@ -24,7 +24,7 @@
@@ -2343,7 +2343,7 @@ Returns:
diff --git a/docs/Inversion.html b/docs/Inversion.html
index 216d2b8..178b7a6 100644
--- a/docs/Inversion.html
+++ b/docs/Inversion.html
@@ -24,7 +24,7 @@
@@ -232,7 +232,7 @@ Classes
diff --git a/docs/Line.html b/docs/Line.html
index 24726c2..619ba6d 100644
--- a/docs/Line.html
+++ b/docs/Line.html
@@ -24,7 +24,7 @@
@@ -2629,7 +2629,7 @@ Returns:
diff --git a/docs/LinkedList.html b/docs/LinkedList.html
index 3d7e479..225d056 100644
--- a/docs/LinkedList.html
+++ b/docs/LinkedList.html
@@ -24,7 +24,7 @@
@@ -1094,7 +1094,7 @@ Returns:
diff --git a/docs/Matrix.html b/docs/Matrix.html
index 7ee2584..e031435 100644
--- a/docs/Matrix.html
+++ b/docs/Matrix.html
@@ -24,7 +24,7 @@
@@ -1613,7 +1613,7 @@ Returns:
diff --git a/docs/Multiline.html b/docs/Multiline.html
index aec92f0..cb2fe08 100644
--- a/docs/Multiline.html
+++ b/docs/Multiline.html
@@ -24,7 +24,7 @@
@@ -100,7 +100,7 @@ new Multilin
Source:
@@ -202,7 +202,7 @@ boxSource:
@@ -266,7 +266,7 @@ edgesSource:
@@ -330,7 +330,7 @@ verticesSource:
@@ -404,7 +404,7 @@ addVertexSource:
@@ -586,7 +586,7 @@ cloneSource:
@@ -690,7 +690,7 @@ findEd
Source:
@@ -848,7 +848,7 @@ rotateSource:
@@ -993,6 +993,90 @@ Returns:
+
+
+
+
+
+
+
+
+
+
+ setArcLength()
+
+
+
+
+
+
+ Set arc_length property for each of the edges in the face.
+Arc_length of the edge it the arc length from the first edge of the face
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1046,7 +1130,7 @@ splitSource:
@@ -1202,7 +1286,7 @@ svgSource:
@@ -1355,7 +1439,7 @@ toJSONSource:
@@ -1459,7 +1543,7 @@ toShapesSource:
@@ -1564,7 +1648,7 @@ transformSource:
@@ -1724,7 +1808,7 @@ translateSource:
@@ -1849,7 +1933,7 @@ Returns:
diff --git a/docs/PlanarSet.html b/docs/PlanarSet.html
index 50db807..b55e198 100644
--- a/docs/PlanarSet.html
+++ b/docs/PlanarSet.html
@@ -24,7 +24,7 @@
@@ -1053,7 +1053,7 @@ Returns:
diff --git a/docs/Point.html b/docs/Point.html
index e5ee07d..10df256 100644
--- a/docs/Point.html
+++ b/docs/Point.html
@@ -24,7 +24,7 @@
@@ -1861,7 +1861,7 @@ Returns:
diff --git a/docs/Polygon.html b/docs/Polygon.html
index ba93408..ffbd128 100644
--- a/docs/Polygon.html
+++ b/docs/Polygon.html
@@ -24,7 +24,7 @@
@@ -1129,7 +1129,7 @@ containsSource:
@@ -1242,16 +1242,14 @@ Returns:
- cut(multiline) → {Array.<Polygon>}
+ cut(multiline) → {Polygon}
- Cut polygon with multiline and return array of new polygons
-Multiline should be constructed from a line with intersection point, see notebook:
-https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ Cut polygon with multiline and return a new polygon
@@ -1287,7 +1285,7 @@ cutSource:
@@ -1381,190 +1379,7 @@ Returns:
-Array.<Polygon>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cutFace(pt1, pt2) → {Array.<Polygon>}
-
-
-
-
-
-
- Cut face of polygon with a segment between two points and create two new polygons
-Supposed that a segments between points does not intersect any other edge
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - Source:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameters:
-
-
-
-
-
-
- Name
-
-
- Type
-
-
-
-
-
- Description
-
-
-
-
-
-
-
-
- pt1
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pt2
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Returns:
-
-
-
-
- -
- Type:
-
- -
-
-
Array.<Polygon>
+Polygon
@@ -1590,7 +1405,8 @@ cutWithLin
- Return a result of cutting polygon with line
+ A special case of cut() function
+The return is a polygon cut with line
@@ -1626,7 +1442,7 @@ cutWithLin
- Source:
@@ -1942,7 +1758,7 @@ distanceTo<
- Source:
@@ -2102,7 +1918,7 @@ findEd
- Source:
@@ -2258,7 +2074,7 @@ intersectSource:
@@ -3026,7 +2842,7 @@ reverseSource:
@@ -3132,7 +2948,7 @@ rotateSource:
@@ -3330,7 +3146,7 @@ scaleSource:
@@ -3476,8 +3292,8 @@ splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
- Source:
@@ -3617,7 +3433,7 @@ svgSource:
@@ -3768,7 +3584,7 @@ toArraySource:
@@ -3873,7 +3689,7 @@ toJSONSource:
@@ -3977,7 +3793,7 @@ transformSource:
@@ -4137,7 +3953,7 @@ translateSource:
@@ -4262,7 +4078,7 @@ Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
@@ -288,7 +288,7 @@ boxSource:
@@ -352,7 +352,7 @@ endSource:
@@ -416,7 +416,7 @@ lengthSource:
@@ -480,7 +480,7 @@ slopeSource:
@@ -544,7 +544,7 @@ startSource:
@@ -618,7 +618,7 @@ cloneSource:
@@ -722,7 +722,7 @@ containsSource:
@@ -828,6 +828,165 @@ Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+ -
+ classes/ray.js, line 123
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+ -
+ Type:
+
+ -
+
+
number
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
@@ -1038,7 +1197,7 @@ rotateSource:
@@ -1199,7 +1358,7 @@ splitSource:
@@ -1347,7 +1506,7 @@ svgSource:
@@ -1508,7 +1667,7 @@ transformSource:
@@ -1633,7 +1792,7 @@ Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
- Source:
@@ -964,7 +964,7 @@ (constant) pol
- Source:
@@ -2466,7 +2466,7 @@ Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
setOverlap<
Source:
@@ -1819,7 +1819,7 @@ Parameters:
diff --git a/docs/Errors.html b/docs/Errors.html
index c6bde70..e68d0b8 100644
--- a/docs/Errors.html
+++ b/docs/Errors.html
@@ -24,7 +24,7 @@
@@ -426,7 +426,7 @@ (static)
diff --git a/docs/Face.html b/docs/Face.html
index bb2a134..4b59c72 100644
--- a/docs/Face.html
+++ b/docs/Face.html
@@ -24,7 +24,7 @@
@@ -2343,7 +2343,7 @@ Returns:
diff --git a/docs/Inversion.html b/docs/Inversion.html
index 216d2b8..178b7a6 100644
--- a/docs/Inversion.html
+++ b/docs/Inversion.html
@@ -24,7 +24,7 @@
@@ -232,7 +232,7 @@ Classes
diff --git a/docs/Line.html b/docs/Line.html
index 24726c2..619ba6d 100644
--- a/docs/Line.html
+++ b/docs/Line.html
@@ -24,7 +24,7 @@
@@ -2629,7 +2629,7 @@ Returns:
diff --git a/docs/LinkedList.html b/docs/LinkedList.html
index 3d7e479..225d056 100644
--- a/docs/LinkedList.html
+++ b/docs/LinkedList.html
@@ -24,7 +24,7 @@
@@ -1094,7 +1094,7 @@ Returns:
diff --git a/docs/Matrix.html b/docs/Matrix.html
index 7ee2584..e031435 100644
--- a/docs/Matrix.html
+++ b/docs/Matrix.html
@@ -24,7 +24,7 @@
@@ -1613,7 +1613,7 @@ Returns:
diff --git a/docs/Multiline.html b/docs/Multiline.html
index aec92f0..cb2fe08 100644
--- a/docs/Multiline.html
+++ b/docs/Multiline.html
@@ -24,7 +24,7 @@
@@ -100,7 +100,7 @@ new Multilin
Source:
@@ -202,7 +202,7 @@ boxSource:
@@ -266,7 +266,7 @@ edgesSource:
@@ -330,7 +330,7 @@ verticesSource:
@@ -404,7 +404,7 @@ addVertexSource:
@@ -586,7 +586,7 @@ cloneSource:
@@ -690,7 +690,7 @@ findEd
Source:
@@ -848,7 +848,7 @@ rotateSource:
@@ -993,6 +993,90 @@ Returns:
+
+
+
+
+
+
+
+
+
+
+ setArcLength()
+
+
+
+
+
+
+ Set arc_length property for each of the edges in the face.
+Arc_length of the edge it the arc length from the first edge of the face
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1046,7 +1130,7 @@ splitSource:
@@ -1202,7 +1286,7 @@ svgSource:
@@ -1355,7 +1439,7 @@ toJSONSource:
@@ -1459,7 +1543,7 @@ toShapesSource:
@@ -1564,7 +1648,7 @@ transformSource:
@@ -1724,7 +1808,7 @@ translateSource:
@@ -1849,7 +1933,7 @@ Returns:
diff --git a/docs/PlanarSet.html b/docs/PlanarSet.html
index 50db807..b55e198 100644
--- a/docs/PlanarSet.html
+++ b/docs/PlanarSet.html
@@ -24,7 +24,7 @@
@@ -1053,7 +1053,7 @@ Returns:
diff --git a/docs/Point.html b/docs/Point.html
index e5ee07d..10df256 100644
--- a/docs/Point.html
+++ b/docs/Point.html
@@ -24,7 +24,7 @@
@@ -1861,7 +1861,7 @@ Returns:
diff --git a/docs/Polygon.html b/docs/Polygon.html
index ba93408..ffbd128 100644
--- a/docs/Polygon.html
+++ b/docs/Polygon.html
@@ -24,7 +24,7 @@
@@ -1129,7 +1129,7 @@ containsSource:
@@ -1242,16 +1242,14 @@ Returns:
- cut(multiline) → {Array.<Polygon>}
+ cut(multiline) → {Polygon}
- Cut polygon with multiline and return array of new polygons
-Multiline should be constructed from a line with intersection point, see notebook:
-https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ Cut polygon with multiline and return a new polygon
@@ -1287,7 +1285,7 @@ cutSource:
@@ -1381,190 +1379,7 @@ Returns:
-Array.<Polygon>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cutFace(pt1, pt2) → {Array.<Polygon>}
-
-
-
-
-
-
- Cut face of polygon with a segment between two points and create two new polygons
-Supposed that a segments between points does not intersect any other edge
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - Source:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameters:
-
-
-
-
-
-
- Name
-
-
- Type
-
-
-
-
-
- Description
-
-
-
-
-
-
-
-
- pt1
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pt2
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Returns:
-
-
-
-
- -
- Type:
-
- -
-
-
Array.<Polygon>
+Polygon
@@ -1590,7 +1405,8 @@ cutWithLin
- Return a result of cutting polygon with line
+ A special case of cut() function
+The return is a polygon cut with line
@@ -1626,7 +1442,7 @@ cutWithLin
- Source:
@@ -1942,7 +1758,7 @@ distanceTo<
- Source:
@@ -2102,7 +1918,7 @@ findEd
- Source:
@@ -2258,7 +2074,7 @@ intersectSource:
@@ -3026,7 +2842,7 @@ reverseSource:
@@ -3132,7 +2948,7 @@ rotateSource:
@@ -3330,7 +3146,7 @@ scaleSource:
@@ -3476,8 +3292,8 @@ splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
- Source:
@@ -3617,7 +3433,7 @@ svgSource:
@@ -3768,7 +3584,7 @@ toArraySource:
@@ -3873,7 +3689,7 @@ toJSONSource:
@@ -3977,7 +3793,7 @@ transformSource:
@@ -4137,7 +3953,7 @@ translateSource:
@@ -4262,7 +4078,7 @@ Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
@@ -288,7 +288,7 @@ boxSource:
@@ -352,7 +352,7 @@ endSource:
@@ -416,7 +416,7 @@ lengthSource:
@@ -480,7 +480,7 @@ slopeSource:
@@ -544,7 +544,7 @@ startSource:
@@ -618,7 +618,7 @@ cloneSource:
@@ -722,7 +722,7 @@ containsSource:
@@ -828,6 +828,165 @@ Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+ -
+ classes/ray.js, line 123
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+ -
+ Type:
+
+ -
+
+
number
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
@@ -1038,7 +1197,7 @@ rotateSource:
@@ -1199,7 +1358,7 @@ splitSource:
@@ -1347,7 +1506,7 @@ svgSource:
@@ -1508,7 +1667,7 @@ transformSource:
@@ -1633,7 +1792,7 @@ Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
- Source:
@@ -964,7 +964,7 @@ (constant) pol
- Source:
@@ -2466,7 +2466,7 @@ Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
(static)
diff --git a/docs/Face.html b/docs/Face.html
index bb2a134..4b59c72 100644
--- a/docs/Face.html
+++ b/docs/Face.html
@@ -24,7 +24,7 @@
@@ -2343,7 +2343,7 @@ Returns:
diff --git a/docs/Inversion.html b/docs/Inversion.html
index 216d2b8..178b7a6 100644
--- a/docs/Inversion.html
+++ b/docs/Inversion.html
@@ -24,7 +24,7 @@
@@ -232,7 +232,7 @@ Classes
diff --git a/docs/Line.html b/docs/Line.html
index 24726c2..619ba6d 100644
--- a/docs/Line.html
+++ b/docs/Line.html
@@ -24,7 +24,7 @@
@@ -2629,7 +2629,7 @@ Returns:
diff --git a/docs/LinkedList.html b/docs/LinkedList.html
index 3d7e479..225d056 100644
--- a/docs/LinkedList.html
+++ b/docs/LinkedList.html
@@ -24,7 +24,7 @@
@@ -1094,7 +1094,7 @@ Returns:
diff --git a/docs/Matrix.html b/docs/Matrix.html
index 7ee2584..e031435 100644
--- a/docs/Matrix.html
+++ b/docs/Matrix.html
@@ -24,7 +24,7 @@
@@ -1613,7 +1613,7 @@ Returns:
diff --git a/docs/Multiline.html b/docs/Multiline.html
index aec92f0..cb2fe08 100644
--- a/docs/Multiline.html
+++ b/docs/Multiline.html
@@ -24,7 +24,7 @@
@@ -100,7 +100,7 @@ new Multilin
Source:
@@ -202,7 +202,7 @@ boxSource:
@@ -266,7 +266,7 @@ edgesSource:
@@ -330,7 +330,7 @@ verticesSource:
@@ -404,7 +404,7 @@ addVertexSource:
@@ -586,7 +586,7 @@ cloneSource:
@@ -690,7 +690,7 @@ findEd
Source:
@@ -848,7 +848,7 @@ rotateSource:
@@ -993,6 +993,90 @@ Returns:
+
+
+
+
+
+
+
+
+
+
+ setArcLength()
+
+
+
+
+
+
+ Set arc_length property for each of the edges in the face.
+Arc_length of the edge it the arc length from the first edge of the face
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1046,7 +1130,7 @@ splitSource:
@@ -1202,7 +1286,7 @@ svgSource:
@@ -1355,7 +1439,7 @@ toJSONSource:
@@ -1459,7 +1543,7 @@ toShapesSource:
@@ -1564,7 +1648,7 @@ transformSource:
@@ -1724,7 +1808,7 @@ translateSource:
@@ -1849,7 +1933,7 @@ Returns:
diff --git a/docs/PlanarSet.html b/docs/PlanarSet.html
index 50db807..b55e198 100644
--- a/docs/PlanarSet.html
+++ b/docs/PlanarSet.html
@@ -24,7 +24,7 @@
@@ -1053,7 +1053,7 @@ Returns:
diff --git a/docs/Point.html b/docs/Point.html
index e5ee07d..10df256 100644
--- a/docs/Point.html
+++ b/docs/Point.html
@@ -24,7 +24,7 @@
@@ -1861,7 +1861,7 @@ Returns:
diff --git a/docs/Polygon.html b/docs/Polygon.html
index ba93408..ffbd128 100644
--- a/docs/Polygon.html
+++ b/docs/Polygon.html
@@ -24,7 +24,7 @@
@@ -1129,7 +1129,7 @@ containsSource:
@@ -1242,16 +1242,14 @@ Returns:
- cut(multiline) → {Array.<Polygon>}
+ cut(multiline) → {Polygon}
- Cut polygon with multiline and return array of new polygons
-Multiline should be constructed from a line with intersection point, see notebook:
-https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ Cut polygon with multiline and return a new polygon
@@ -1287,7 +1285,7 @@ cutSource:
@@ -1381,190 +1379,7 @@ Returns:
-Array.<Polygon>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cutFace(pt1, pt2) → {Array.<Polygon>}
-
-
-
-
-
-
- Cut face of polygon with a segment between two points and create two new polygons
-Supposed that a segments between points does not intersect any other edge
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - Source:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameters:
-
-
-
-
-
-
- Name
-
-
- Type
-
-
-
-
-
- Description
-
-
-
-
-
-
-
-
- pt1
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pt2
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Returns:
-
-
-
-
- -
- Type:
-
- -
-
-
Array.<Polygon>
+Polygon
@@ -1590,7 +1405,8 @@ cutWithLin
- Return a result of cutting polygon with line
+ A special case of cut() function
+The return is a polygon cut with line
@@ -1626,7 +1442,7 @@ cutWithLin
- Source:
@@ -1942,7 +1758,7 @@ distanceTo<
- Source:
@@ -2102,7 +1918,7 @@ findEd
- Source:
@@ -2258,7 +2074,7 @@ intersectSource:
@@ -3026,7 +2842,7 @@ reverseSource:
@@ -3132,7 +2948,7 @@ rotateSource:
@@ -3330,7 +3146,7 @@ scaleSource:
@@ -3476,8 +3292,8 @@ splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
- Source:
@@ -3617,7 +3433,7 @@ svgSource:
@@ -3768,7 +3584,7 @@ toArraySource:
@@ -3873,7 +3689,7 @@ toJSONSource:
@@ -3977,7 +3793,7 @@ transformSource:
@@ -4137,7 +3953,7 @@ translateSource:
@@ -4262,7 +4078,7 @@ Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
@@ -288,7 +288,7 @@ boxSource:
@@ -352,7 +352,7 @@ endSource:
@@ -416,7 +416,7 @@ lengthSource:
@@ -480,7 +480,7 @@ slopeSource:
@@ -544,7 +544,7 @@ startSource:
@@ -618,7 +618,7 @@ cloneSource:
@@ -722,7 +722,7 @@ containsSource:
@@ -828,6 +828,165 @@ Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+ -
+ classes/ray.js, line 123
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+ -
+ Type:
+
+ -
+
+
number
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
@@ -1038,7 +1197,7 @@ rotateSource:
@@ -1199,7 +1358,7 @@ splitSource:
@@ -1347,7 +1506,7 @@ svgSource:
@@ -1508,7 +1667,7 @@ transformSource:
@@ -1633,7 +1792,7 @@ Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
- Source:
@@ -964,7 +964,7 @@ (constant) pol
- Source:
@@ -2466,7 +2466,7 @@ Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
Returns:
diff --git a/docs/Inversion.html b/docs/Inversion.html index 216d2b8..178b7a6 100644 --- a/docs/Inversion.html +++ b/docs/Inversion.html @@ -24,7 +24,7 @@
Classes
diff --git a/docs/Line.html b/docs/Line.html index 24726c2..619ba6d 100644 --- a/docs/Line.html +++ b/docs/Line.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/LinkedList.html b/docs/LinkedList.html index 3d7e479..225d056 100644 --- a/docs/LinkedList.html +++ b/docs/LinkedList.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/Matrix.html b/docs/Matrix.html index 7ee2584..e031435 100644 --- a/docs/Matrix.html +++ b/docs/Matrix.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/Multiline.html b/docs/Multiline.html index aec92f0..cb2fe08 100644 --- a/docs/Multiline.html +++ b/docs/Multiline.html @@ -24,7 +24,7 @@
new Multilin
Source:
@@ -202,7 +202,7 @@ boxSource:
@@ -266,7 +266,7 @@ edgesSource:
@@ -330,7 +330,7 @@ verticesSource:
@@ -404,7 +404,7 @@ addVertexSource:
@@ -586,7 +586,7 @@ cloneSource:
@@ -690,7 +690,7 @@ findEd
Source:
@@ -848,7 +848,7 @@ rotateSource:
@@ -993,6 +993,90 @@ Returns:
edgesSource:
@@ -330,7 +330,7 @@ verticesSource:
@@ -404,7 +404,7 @@ addVertexSource:
@@ -586,7 +586,7 @@ cloneSource:
@@ -690,7 +690,7 @@ findEd
Source:
@@ -848,7 +848,7 @@ rotateSource:
@@ -993,6 +993,90 @@ Returns:
addVertexSource:
@@ -586,7 +586,7 @@ cloneSource:
@@ -690,7 +690,7 @@ findEd
Source:
@@ -848,7 +848,7 @@ rotateSource:
@@ -993,6 +993,90 @@ Returns:
cloneSource:
@@ -690,7 +690,7 @@ findEd
Source:
@@ -848,7 +848,7 @@ rotateSource:
@@ -993,6 +993,90 @@ Returns:
rotateSource:
@@ -993,6 +993,90 @@ Returns:
setArcLength()
+ + + + + +-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- Source: +
- + + + + + + + +
splitSource:
@@ -1202,7 +1286,7 @@ svgSource:
@@ -1355,7 +1439,7 @@ toJSONSource:
@@ -1459,7 +1543,7 @@ toShapesSource:
@@ -1564,7 +1648,7 @@ transformSource:
@@ -1724,7 +1808,7 @@ translateSource:
@@ -1849,7 +1933,7 @@ Returns:
diff --git a/docs/PlanarSet.html b/docs/PlanarSet.html
index 50db807..b55e198 100644
--- a/docs/PlanarSet.html
+++ b/docs/PlanarSet.html
@@ -24,7 +24,7 @@
@@ -1053,7 +1053,7 @@ Returns:
diff --git a/docs/Point.html b/docs/Point.html
index e5ee07d..10df256 100644
--- a/docs/Point.html
+++ b/docs/Point.html
@@ -24,7 +24,7 @@
@@ -1861,7 +1861,7 @@ Returns:
diff --git a/docs/Polygon.html b/docs/Polygon.html
index ba93408..ffbd128 100644
--- a/docs/Polygon.html
+++ b/docs/Polygon.html
@@ -24,7 +24,7 @@
@@ -1129,7 +1129,7 @@ containsSource:
@@ -1242,16 +1242,14 @@ Returns:
- cut(multiline) → {Array.<Polygon>}
+ cut(multiline) → {Polygon}
- Cut polygon with multiline and return array of new polygons
-Multiline should be constructed from a line with intersection point, see notebook:
-https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ Cut polygon with multiline and return a new polygon
@@ -1287,7 +1285,7 @@ cutSource:
@@ -1381,190 +1379,7 @@ Returns:
-Array.<Polygon>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cutFace(pt1, pt2) → {Array.<Polygon>}
-
-
-
-
-
-
- Cut face of polygon with a segment between two points and create two new polygons
-Supposed that a segments between points does not intersect any other edge
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - Source:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameters:
-
-
-
-
-
-
- Name
-
-
- Type
-
-
-
-
-
- Description
-
-
-
-
-
-
-
-
- pt1
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pt2
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Returns:
-
-
-
-
- -
- Type:
-
- -
-
-
Array.<Polygon>
+Polygon
@@ -1590,7 +1405,8 @@ cutWithLin
- Return a result of cutting polygon with line
+ A special case of cut() function
+The return is a polygon cut with line
@@ -1626,7 +1442,7 @@ cutWithLin
- Source:
@@ -1942,7 +1758,7 @@ distanceTo<
- Source:
@@ -2102,7 +1918,7 @@ findEd
- Source:
@@ -2258,7 +2074,7 @@ intersectSource:
@@ -3026,7 +2842,7 @@ reverseSource:
@@ -3132,7 +2948,7 @@ rotateSource:
@@ -3330,7 +3146,7 @@ scaleSource:
@@ -3476,8 +3292,8 @@ splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
- Source:
@@ -3617,7 +3433,7 @@ svgSource:
@@ -3768,7 +3584,7 @@ toArraySource:
@@ -3873,7 +3689,7 @@ toJSONSource:
@@ -3977,7 +3793,7 @@ transformSource:
@@ -4137,7 +3953,7 @@ translateSource:
@@ -4262,7 +4078,7 @@ Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
@@ -288,7 +288,7 @@ boxSource:
@@ -352,7 +352,7 @@ endSource:
@@ -416,7 +416,7 @@ lengthSource:
@@ -480,7 +480,7 @@ slopeSource:
@@ -544,7 +544,7 @@ startSource:
@@ -618,7 +618,7 @@ cloneSource:
@@ -722,7 +722,7 @@ containsSource:
@@ -828,6 +828,165 @@ Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+ -
+ classes/ray.js, line 123
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+ -
+ Type:
+
+ -
+
+
number
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
@@ -1038,7 +1197,7 @@ rotateSource:
@@ -1199,7 +1358,7 @@ splitSource:
@@ -1347,7 +1506,7 @@ svgSource:
@@ -1508,7 +1667,7 @@ transformSource:
@@ -1633,7 +1792,7 @@ Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
- Source:
@@ -964,7 +964,7 @@ (constant) pol
- Source:
@@ -2466,7 +2466,7 @@ Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
toJSONSource:
@@ -1459,7 +1543,7 @@ toShapesSource:
@@ -1564,7 +1648,7 @@ transformSource:
@@ -1724,7 +1808,7 @@ translateSource:
@@ -1849,7 +1933,7 @@ Returns:
diff --git a/docs/PlanarSet.html b/docs/PlanarSet.html
index 50db807..b55e198 100644
--- a/docs/PlanarSet.html
+++ b/docs/PlanarSet.html
@@ -24,7 +24,7 @@
@@ -1053,7 +1053,7 @@ Returns:
diff --git a/docs/Point.html b/docs/Point.html
index e5ee07d..10df256 100644
--- a/docs/Point.html
+++ b/docs/Point.html
@@ -24,7 +24,7 @@
@@ -1861,7 +1861,7 @@ Returns:
diff --git a/docs/Polygon.html b/docs/Polygon.html
index ba93408..ffbd128 100644
--- a/docs/Polygon.html
+++ b/docs/Polygon.html
@@ -24,7 +24,7 @@
@@ -1129,7 +1129,7 @@ containsSource:
@@ -1242,16 +1242,14 @@ Returns:
- cut(multiline) → {Array.<Polygon>}
+ cut(multiline) → {Polygon}
- Cut polygon with multiline and return array of new polygons
-Multiline should be constructed from a line with intersection point, see notebook:
-https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ Cut polygon with multiline and return a new polygon
@@ -1287,7 +1285,7 @@ cutSource:
@@ -1381,190 +1379,7 @@ Returns:
-Array.<Polygon>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cutFace(pt1, pt2) → {Array.<Polygon>}
-
-
-
-
-
-
- Cut face of polygon with a segment between two points and create two new polygons
-Supposed that a segments between points does not intersect any other edge
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - Source:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameters:
-
-
-
-
-
-
- Name
-
-
- Type
-
-
-
-
-
- Description
-
-
-
-
-
-
-
-
- pt1
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pt2
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Returns:
-
-
-
-
- -
- Type:
-
- -
-
-
Array.<Polygon>
+Polygon
@@ -1590,7 +1405,8 @@ cutWithLin
- Return a result of cutting polygon with line
+ A special case of cut() function
+The return is a polygon cut with line
@@ -1626,7 +1442,7 @@ cutWithLin
- Source:
@@ -1942,7 +1758,7 @@ distanceTo<
- Source:
@@ -2102,7 +1918,7 @@ findEd
- Source:
@@ -2258,7 +2074,7 @@ intersectSource:
@@ -3026,7 +2842,7 @@ reverseSource:
@@ -3132,7 +2948,7 @@ rotateSource:
@@ -3330,7 +3146,7 @@ scaleSource:
@@ -3476,8 +3292,8 @@ splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
- Source:
@@ -3617,7 +3433,7 @@ svgSource:
@@ -3768,7 +3584,7 @@ toArraySource:
@@ -3873,7 +3689,7 @@ toJSONSource:
@@ -3977,7 +3793,7 @@ transformSource:
@@ -4137,7 +3953,7 @@ translateSource:
@@ -4262,7 +4078,7 @@ Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
@@ -288,7 +288,7 @@ boxSource:
@@ -352,7 +352,7 @@ endSource:
@@ -416,7 +416,7 @@ lengthSource:
@@ -480,7 +480,7 @@ slopeSource:
@@ -544,7 +544,7 @@ startSource:
@@ -618,7 +618,7 @@ cloneSource:
@@ -722,7 +722,7 @@ containsSource:
@@ -828,6 +828,165 @@ Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+ -
+ classes/ray.js, line 123
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+ -
+ Type:
+
+ -
+
+
number
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
@@ -1038,7 +1197,7 @@ rotateSource:
@@ -1199,7 +1358,7 @@ splitSource:
@@ -1347,7 +1506,7 @@ svgSource:
@@ -1508,7 +1667,7 @@ transformSource:
@@ -1633,7 +1792,7 @@ Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
- Source:
@@ -964,7 +964,7 @@ (constant) pol
- Source:
@@ -2466,7 +2466,7 @@ Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
transformSource:
@@ -1724,7 +1808,7 @@ translateSource:
@@ -1849,7 +1933,7 @@ Returns:
diff --git a/docs/PlanarSet.html b/docs/PlanarSet.html
index 50db807..b55e198 100644
--- a/docs/PlanarSet.html
+++ b/docs/PlanarSet.html
@@ -24,7 +24,7 @@
@@ -1053,7 +1053,7 @@ Returns:
diff --git a/docs/Point.html b/docs/Point.html
index e5ee07d..10df256 100644
--- a/docs/Point.html
+++ b/docs/Point.html
@@ -24,7 +24,7 @@
@@ -1861,7 +1861,7 @@ Returns:
diff --git a/docs/Polygon.html b/docs/Polygon.html
index ba93408..ffbd128 100644
--- a/docs/Polygon.html
+++ b/docs/Polygon.html
@@ -24,7 +24,7 @@
@@ -1129,7 +1129,7 @@ containsSource:
@@ -1242,16 +1242,14 @@ Returns:
- cut(multiline) → {Array.<Polygon>}
+ cut(multiline) → {Polygon}
- Cut polygon with multiline and return array of new polygons
-Multiline should be constructed from a line with intersection point, see notebook:
-https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ Cut polygon with multiline and return a new polygon
@@ -1287,7 +1285,7 @@ cutSource:
@@ -1381,190 +1379,7 @@ Returns:
-Array.<Polygon>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cutFace(pt1, pt2) → {Array.<Polygon>}
-
-
-
-
-
-
- Cut face of polygon with a segment between two points and create two new polygons
-Supposed that a segments between points does not intersect any other edge
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - Source:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameters:
-
-
-
-
-
-
- Name
-
-
- Type
-
-
-
-
-
- Description
-
-
-
-
-
-
-
-
- pt1
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pt2
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Returns:
-
-
-
-
- -
- Type:
-
- -
-
-
Array.<Polygon>
+Polygon
@@ -1590,7 +1405,8 @@ cutWithLin
- Return a result of cutting polygon with line
+ A special case of cut() function
+The return is a polygon cut with line
@@ -1626,7 +1442,7 @@ cutWithLin
- Source:
@@ -1942,7 +1758,7 @@ distanceTo<
- Source:
@@ -2102,7 +1918,7 @@ findEd
- Source:
@@ -2258,7 +2074,7 @@ intersectSource:
@@ -3026,7 +2842,7 @@ reverseSource:
@@ -3132,7 +2948,7 @@ rotateSource:
@@ -3330,7 +3146,7 @@ scaleSource:
@@ -3476,8 +3292,8 @@ splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
- Source:
@@ -3617,7 +3433,7 @@ svgSource:
@@ -3768,7 +3584,7 @@ toArraySource:
@@ -3873,7 +3689,7 @@ toJSONSource:
@@ -3977,7 +3793,7 @@ transformSource:
@@ -4137,7 +3953,7 @@ translateSource:
@@ -4262,7 +4078,7 @@ Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
@@ -288,7 +288,7 @@ boxSource:
@@ -352,7 +352,7 @@ endSource:
@@ -416,7 +416,7 @@ lengthSource:
@@ -480,7 +480,7 @@ slopeSource:
@@ -544,7 +544,7 @@ startSource:
@@ -618,7 +618,7 @@ cloneSource:
@@ -722,7 +722,7 @@ containsSource:
@@ -828,6 +828,165 @@ Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+ -
+ classes/ray.js, line 123
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+ -
+ Type:
+
+ -
+
+
number
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
@@ -1038,7 +1197,7 @@ rotateSource:
@@ -1199,7 +1358,7 @@ splitSource:
@@ -1347,7 +1506,7 @@ svgSource:
@@ -1508,7 +1667,7 @@ transformSource:
@@ -1633,7 +1792,7 @@ Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
- Source:
@@ -964,7 +964,7 @@ (constant) pol
- Source:
@@ -2466,7 +2466,7 @@ Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
translateSource:
@@ -1849,7 +1933,7 @@ Returns:
diff --git a/docs/PlanarSet.html b/docs/PlanarSet.html
index 50db807..b55e198 100644
--- a/docs/PlanarSet.html
+++ b/docs/PlanarSet.html
@@ -24,7 +24,7 @@
@@ -1053,7 +1053,7 @@ Returns:
diff --git a/docs/Point.html b/docs/Point.html
index e5ee07d..10df256 100644
--- a/docs/Point.html
+++ b/docs/Point.html
@@ -24,7 +24,7 @@
@@ -1861,7 +1861,7 @@ Returns:
diff --git a/docs/Polygon.html b/docs/Polygon.html
index ba93408..ffbd128 100644
--- a/docs/Polygon.html
+++ b/docs/Polygon.html
@@ -24,7 +24,7 @@
@@ -1129,7 +1129,7 @@ containsSource:
@@ -1242,16 +1242,14 @@ Returns:
- cut(multiline) → {Array.<Polygon>}
+ cut(multiline) → {Polygon}
- Cut polygon with multiline and return array of new polygons
-Multiline should be constructed from a line with intersection point, see notebook:
-https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ Cut polygon with multiline and return a new polygon
@@ -1287,7 +1285,7 @@ cutSource:
@@ -1381,190 +1379,7 @@ Returns:
-Array.<Polygon>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cutFace(pt1, pt2) → {Array.<Polygon>}
-
-
-
-
-
-
- Cut face of polygon with a segment between two points and create two new polygons
-Supposed that a segments between points does not intersect any other edge
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - Source:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Parameters:
-
-
-
-
-
-
- Name
-
-
- Type
-
-
-
-
-
- Description
-
-
-
-
-
-
-
-
- pt1
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pt2
-
-
-
-
-
-Point
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Returns:
-
-
-
-
- -
- Type:
-
- -
-
-
Array.<Polygon>
+Polygon
@@ -1590,7 +1405,8 @@ cutWithLin
- Return a result of cutting polygon with line
+ A special case of cut() function
+The return is a polygon cut with line
@@ -1626,7 +1442,7 @@ cutWithLin
- Source:
@@ -1942,7 +1758,7 @@ distanceTo<
- Source:
@@ -2102,7 +1918,7 @@ findEd
- Source:
@@ -2258,7 +2074,7 @@ intersectSource:
@@ -3026,7 +2842,7 @@ reverseSource:
@@ -3132,7 +2948,7 @@ rotateSource:
@@ -3330,7 +3146,7 @@ scaleSource:
@@ -3476,8 +3292,8 @@ splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
- Source:
@@ -3617,7 +3433,7 @@ svgSource:
@@ -3768,7 +3584,7 @@ toArraySource:
@@ -3873,7 +3689,7 @@ toJSONSource:
@@ -3977,7 +3793,7 @@ transformSource:
@@ -4137,7 +3953,7 @@ translateSource:
@@ -4262,7 +4078,7 @@ Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
@@ -288,7 +288,7 @@ boxSource:
@@ -352,7 +352,7 @@ endSource:
@@ -416,7 +416,7 @@ lengthSource:
@@ -480,7 +480,7 @@ slopeSource:
@@ -544,7 +544,7 @@ startSource:
@@ -618,7 +618,7 @@ cloneSource:
@@ -722,7 +722,7 @@ containsSource:
@@ -828,6 +828,165 @@ Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+ -
+ classes/ray.js, line 123
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+ -
+ Type:
+
+ -
+
+
number
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
@@ -1038,7 +1197,7 @@ rotateSource:
@@ -1199,7 +1358,7 @@ splitSource:
@@ -1347,7 +1506,7 @@ svgSource:
@@ -1508,7 +1667,7 @@ transformSource:
@@ -1633,7 +1792,7 @@ Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
- Source:
@@ -964,7 +964,7 @@ (constant) pol
- Source:
@@ -2466,7 +2466,7 @@ Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
Returns:
diff --git a/docs/PlanarSet.html b/docs/PlanarSet.html index 50db807..b55e198 100644 --- a/docs/PlanarSet.html +++ b/docs/PlanarSet.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/Point.html b/docs/Point.html index e5ee07d..10df256 100644 --- a/docs/Point.html +++ b/docs/Point.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/Polygon.html b/docs/Polygon.html index ba93408..ffbd128 100644 --- a/docs/Polygon.html +++ b/docs/Polygon.html @@ -24,7 +24,7 @@
containsSource:
@@ -1242,16 +1242,14 @@ Returns:
- cut(multiline) → {Array.<Polygon>}
+ cut(multiline) → {Polygon}
- Cut polygon with multiline and return array of new polygons
-Multiline should be constructed from a line with intersection point, see notebook:
-https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ Cut polygon with multiline and return a new polygon
@@ -1287,7 +1285,7 @@ cutSource:
@@ -1381,190 +1379,7 @@ Returns:
-Array.<Polygon>
-
-
-
-
-
-
-
-
Returns:
Array.<Polygon>
-
-
- cutFace(pt1, pt2) → {Array.<Polygon>}
- - - - - --
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Source: -
- - - - - - - - -
Parameters:
- - -Name | - - -Type | - - - - - -Description | -
---|---|---|
pt1 |
-
-
-
-
-
-Point
-
-
-
- |
-
-
-
-
-
- - - - | -
pt2 |
-
-
-
-
-
-Point
-
-
-
- |
-
-
-
-
-
- - - - | -
Returns:
- - - --
-
- - Type: - -
-
-
-
Array.<Polygon>
+Polygon
@@ -1590,7 +1405,8 @@ - Source:
- @@ -1942,7 +1758,7 @@
- Source:
- @@ -2102,7 +1918,7 @@
- Source:
- @@ -2258,7 +2074,7 @@
- @@ -3026,7 +2842,7 @@
- @@ -3132,7 +2948,7 @@
- @@ -3330,7 +3146,7 @@
- @@ -3476,8 +3292,8 @@
- Source:
- @@ -3617,7 +3433,7 @@
- @@ -3768,7 +3584,7 @@
- @@ -3873,7 +3689,7 @@
- @@ -3977,7 +3793,7 @@
- @@ -4137,7 +3953,7 @@
- @@ -4262,7 +4078,7 @@
- @@ -288,7 +288,7 @@
- @@ -352,7 +352,7 @@
- @@ -416,7 +416,7 @@
- @@ -480,7 +480,7 @@
- @@ -544,7 +544,7 @@
- @@ -618,7 +618,7 @@
- @@ -722,7 +722,7 @@
- @@ -828,6 +828,165 @@
- Source: +
- + classes/ray.js, line 123 +
+
+
+
+
+
+
+
+- + Type: + +
-
+
+
number
+ + +
+ - @@ -1038,7 +1197,7 @@
- @@ -1199,7 +1358,7 @@
- @@ -1347,7 +1506,7 @@
- @@ -1508,7 +1667,7 @@
- @@ -1633,7 +1792,7 @@
- Source:
- @@ -964,7 +964,7 @@
- Source:
- @@ -2466,7 +2466,7 @@
cutWithLin
- Return a result of cutting polygon with line
+ A special case of cut() function
+The return is a polygon cut with line
@@ -1626,7 +1442,7 @@ cutWithLin
distanceTo<
findEd
intersectSource:
reverseSource:
rotateSource:
scaleSource:
splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
svgSource:
toArraySource:
toJSONSource:
transformSource:
translateSource:
Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
boxSource:
endSource:
lengthSource:
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
rotateSource:
splitSource:
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
distanceTo<
findEd
intersectSource:
reverseSource:
rotateSource:
scaleSource:
splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
svgSource:
toArraySource:
toJSONSource:
transformSource:
translateSource:
Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
boxSource:
endSource:
lengthSource:
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
rotateSource:
splitSource:
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
intersectSource:
reverseSource:
rotateSource:
scaleSource:
splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
svgSource:
toArraySource:
toJSONSource:
transformSource:
translateSource:
Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
boxSource:
endSource:
lengthSource:
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
rotateSource:
splitSource:
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
reverseSource:
rotateSource:
scaleSource:
splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
svgSource:
toArraySource:
toJSONSource:
transformSource:
translateSource:
Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
boxSource:
endSource:
lengthSource:
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
rotateSource:
splitSource:
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
scaleSource:
splitTo
- Split polygon into array of polygons, where each polygon is an island with all
-hole that it contains
+ Split polygon into array of polygons, where each polygon is an outer face with all
+containing inner faces
@@ -3513,7 +3329,7 @@ splitTo
svgSource:
toArraySource:
toJSONSource:
transformSource:
translateSource:
Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
boxSource:
endSource:
lengthSource:
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
rotateSource:
splitSource:
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
splitTo
svgSource:
toArraySource:
toJSONSource:
transformSource:
translateSource:
Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
boxSource:
endSource:
lengthSource:
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
rotateSource:
splitSource:
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
toArraySource:
toJSONSource:
transformSource:
translateSource:
Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
boxSource:
endSource:
lengthSource:
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
rotateSource:
splitSource:
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
transformSource:
translateSource:
Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
boxSource:
endSource:
lengthSource:
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
rotateSource:
splitSource:
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
translateSource:
Returns:
diff --git a/docs/Ray.html b/docs/Ray.html
index ce332fd..4867580 100644
--- a/docs/Ray.html
+++ b/docs/Ray.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ new RaySource:
boxSource:
endSource:
lengthSource:
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
+
+
+
+
+
+
+ coord(pt) → {number}
+
+
+
+
+
+
+ Return coordinate of the point that lies on the ray in the transformed
+coordinate system where center is the projection of the point(0,0) to
+the line containing this ray and axe y is collinear to the normal vector.
+This method assumes that point lies on the ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name
+
+
+ Type
+
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+ pt
+
+
+
+
+
+Point
+
+
+
+
+
+
+
+
+
+
+ point on a ray
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+
+
+
+
+
+
+
+
+
@@ -878,7 +1037,7 @@ intersectSource:
rotateSource:
splitSource:
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
Returns:
diff --git a/docs/Ray.html b/docs/Ray.html index ce332fd..4867580 100644 --- a/docs/Ray.html +++ b/docs/Ray.html @@ -24,7 +24,7 @@
new RaySource:
boxSource:
endSource:
lengthSource:
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
endSource:
lengthSource:
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
slopeSource:
startSource:
cloneSource:
containsSource:
Returns:
+
cloneSource:
containsSource:
Returns:
+
Returns:
+coord(pt) → {number}
+ + + + + ++This method assumes that point lies on the ray +
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Parameters:
+ + +Name | + + +Type | + + + + + +Description | +
---|---|---|
pt |
+
+
+
+
+
+Point
+
+
+
+ |
+
+
+
+
+
+ + point on a ray + + | +
Returns:
+ + + +-
+
intersectSource:
rotateSource:
splitSource:
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
rotateSource:
splitSource:
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
svgSource:
transformSource:
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html
index 221eb70..2964cc6 100644
--- a/docs/Segment.html
+++ b/docs/Segment.html
@@ -24,7 +24,7 @@
@@ -2854,7 +2854,7 @@ Returns:
diff --git a/docs/Shape.html b/docs/Shape.html
index 83a9934..77269d1 100644
--- a/docs/Shape.html
+++ b/docs/Shape.html
@@ -24,7 +24,7 @@
@@ -838,7 +838,7 @@ Returns:
diff --git a/docs/Vector.html b/docs/Vector.html
index 65000b7..51d652d 100644
--- a/docs/Vector.html
+++ b/docs/Vector.html
@@ -24,7 +24,7 @@
@@ -2628,7 +2628,7 @@ Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html
index 5f2cf51..a29035f 100644
--- a/docs/algorithms_boolean_op.js.html
+++ b/docs/algorithms_boolean_op.js.html
@@ -24,7 +24,7 @@
@@ -741,7 +741,7 @@ algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html
index d61b05b..6f81dbe 100644
--- a/docs/algorithms_distance.js.html
+++ b/docs/algorithms_distance.js.html
@@ -24,7 +24,7 @@
@@ -651,7 +651,7 @@ algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html
index 61e578d..6bcc0a9 100644
--- a/docs/algorithms_ray_shooting.js.html
+++ b/docs/algorithms_ray_shooting.js.html
@@ -24,7 +24,7 @@
@@ -194,7 +194,7 @@ algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html
index 41856b7..b93034d 100644
--- a/docs/algorithms_relation.js.html
+++ b/docs/algorithms_relation.js.html
@@ -24,7 +24,7 @@
@@ -244,7 +244,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline);
+ denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line);
}
return denim;
@@ -286,7 +286,7 @@ algorithms/relation.js
denim.I2B = ip_sorted;
denim.I2E = [splitShapes[0], splitShapes[2]];
- denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline);
+ denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line);
}
}
return denim;
@@ -306,7 +306,7 @@ algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start );
denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape);
- denim.E2I = polygon.cut(multiline);
+ denim.E2I = polygon.cutWithLine(line);
return denim;
}
@@ -387,7 +387,7 @@ algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html
index 03bb7c9..5848b6f 100644
--- a/docs/classes_arc.js.html
+++ b/docs/classes_arc.js.html
@@ -24,7 +24,7 @@
@@ -549,7 +549,7 @@ classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html
index 477a6d7..002303e 100644
--- a/docs/classes_box.js.html
+++ b/docs/classes_box.js.html
@@ -24,7 +24,7 @@
@@ -363,7 +363,7 @@ classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html
index 55d4975..456044a 100644
--- a/docs/classes_circle.js.html
+++ b/docs/classes_circle.js.html
@@ -24,7 +24,7 @@
@@ -301,7 +301,7 @@ classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html
index 447d634..3f037b1 100644
--- a/docs/classes_edge.js.html
+++ b/docs/classes_edge.js.html
@@ -24,7 +24,7 @@
@@ -134,14 +134,22 @@ classes/edge.js
return this.shape.box;
}
- isSegment() {
+ get isSegment() {
return this.shape instanceof Flatten.Segment;
}
- isArc() {
+ get isArc() {
return this.shape instanceof Flatten.Arc;
}
+ get isLine() {
+ return this.shape instanceof Flatten.Line;
+ }
+
+ get isRay() {
+ return this.shape instanceof Flatten.Ray
+ }
+
/**
* Get middle point of the edge
* @returns {Point}
@@ -286,7 +294,7 @@ classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html
index b42bed7..e3b4680 100644
--- a/docs/classes_face.js.html
+++ b/docs/classes_face.js.html
@@ -24,7 +24,7 @@
@@ -548,7 +548,7 @@ classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html
index f46dd6a..0a5920e 100644
--- a/docs/classes_inversion.js.html
+++ b/docs/classes_inversion.js.html
@@ -24,7 +24,7 @@
@@ -141,7 +141,7 @@ classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html
index 97331f9..82b4e7e 100644
--- a/docs/classes_line.js.html
+++ b/docs/classes_line.js.html
@@ -24,7 +24,7 @@
@@ -324,7 +324,7 @@ classes/line.js
*/
split(pt) {
if (pt instanceof Flatten.Point) {
- return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)]
+ return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)]
}
else {
let multiline = new Flatten.Multiline([this]);
@@ -425,7 +425,7 @@ classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html
index bb53e6b..dbd2709 100644
--- a/docs/classes_matrix.js.html
+++ b/docs/classes_matrix.js.html
@@ -24,7 +24,7 @@
@@ -202,7 +202,7 @@ classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html
index 1948655..66d46f5 100644
--- a/docs/classes_multiline.js.html
+++ b/docs/classes_multiline.js.html
@@ -24,7 +24,7 @@
@@ -43,7 +43,6 @@ classes/multiline.js
import Flatten from '../flatten';
import LinkedList from '../data_structures/linked_list';
-import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants";
import {convertToString} from "../utils/attributes";
/**
@@ -58,10 +57,10 @@ classes/multiline.js
return;
}
- if (args.length == 1) {
+ if (args.length === 1) {
if (args[0] instanceof Array) {
let shapes = args[0];
- if (shapes.length == 0)
+ if (shapes.length === 0)
return;
// TODO: more strict validation:
@@ -78,6 +77,8 @@ classes/multiline.js
let edge = new Flatten.Edge(shape);
this.append(edge);
}
+
+ this.setArcLength()
}
}
}
@@ -95,7 +96,7 @@ classes/multiline.js
* @returns {Box}
*/
get box() {
- return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() );
+ return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() );
}
/**
@@ -116,6 +117,24 @@ classes/multiline.js
return new Multiline(this.toShapes());
}
+ /**
+ * Set arc_length property for each of the edges in the face.
+ * Arc_length of the edge it the arc length from the first edge of the face
+ */
+ setArcLength() {
+ for (let edge of this) {
+ this.setOneEdgeArcLength(edge);
+ }
+ }
+
+ setOneEdgeArcLength(edge) {
+ if (edge === this.first) {
+ edge.arc_length = 0.0;
+ } else {
+ edge.arc_length = edge.prev.arc_length + edge.prev.length;
+ }
+ }
+
/**
* Split edge and add new vertex, return new edge inserted
* @param {Point} pt - point on edge that will be added as new vertex
@@ -144,6 +163,14 @@ classes/multiline.js
return newEdge;
}
+ getChain(edgeFrom, edgeTo) {
+ let edges = []
+ for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {
+ edges.push(edge)
+ }
+ return edges
+ }
+
/**
* Split edges of multiline with intersection points and return mutated multiline
* @param {Point[]} ip - array of points to be added as new vertices
@@ -258,7 +285,7 @@ classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html
index 48602f2..6923f55 100644
--- a/docs/classes_point.js.html
+++ b/docs/classes_point.js.html
@@ -24,7 +24,7 @@
@@ -308,7 +308,7 @@ classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html
index 423a9c6..017e282 100644
--- a/docs/classes_polygon.js.html
+++ b/docs/classes_polygon.js.html
@@ -24,7 +24,7 @@
@@ -52,11 +52,11 @@ classes/polygon.js
import * as Relations from "../algorithms/relation";
import {
addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections,
- getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints,
+ getSortedArray, initializeInclusionFlags, insertBetweenIntPoints,
splitByIntersections
} from "../data_structures/smart_intersections";
import {Multiline} from "./multiline";
-import {intersectEdge2Line} from "../algorithms/intersection";
+import {intersectEdge2Edge} from "../algorithms/intersection";
import {INSIDE, BOUNDARY} from "../utils/constants";
import {convertToString} from "../utils/attributes";
import {Matrix} from "./matrix";
@@ -332,97 +332,12 @@ classes/polygon.js
}
/**
- * Cut polygon with multiline and return array of new polygons
- * Multiline should be constructed from a line with intersection point, see notebook:
- * https://next.observablehq.com/@alexbol99/cut-polygon-with-line
+ * Cut polygon with multiline and return a new polygon
* @param {Multiline} multiline
- * @returns {Polygon[]}
+ * @returns {Polygon}
*/
cut(multiline) {
- let cutPolygons = [this.clone()];
- for (let edge of multiline) {
- if (edge.setInclusion(this) !== INSIDE)
- continue;
-
- let cut_edge_start = edge.shape.start;
- let cut_edge_end = edge.shape.end;
-
- let newCutPolygons = [];
- for (let polygon of cutPolygons) {
- if (polygon.findEdgeByPoint(cut_edge_start) === undefined) {
- newCutPolygons.push(polygon);
- } else {
- let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end);
- newCutPolygons.push(cutPoly1, cutPoly2);
- }
- }
- cutPolygons = newCutPolygons;
- }
- return cutPolygons;
- }
-
- /**
- * Cut face of polygon with a segment between two points and create two new polygons
- * Supposed that a segments between points does not intersect any other edge
- * @param {Point} pt1
- * @param {Point} pt2
- * @returns {Polygon[]}
- */
- cutFace(pt1, pt2) {
- let edge1 = this.findEdgeByPoint(pt1);
- let edge2 = this.findEdgeByPoint(pt2);
- if (edge1.face !== edge2.face)
- return [];
-
- // Cut face into two and create new polygon with two faces
- let edgeBefore1 = this.addVertex(pt1, edge1);
- edge2 = this.findEdgeByPoint(pt2);
- let edgeBefore2 = this.addVertex(pt2, edge2);
-
- let face = edgeBefore1.face;
- let newEdge1 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore1.end, edgeBefore2.end)
- );
- let newEdge2 = new Flatten.Edge(
- new Flatten.Segment(edgeBefore2.end, edgeBefore1.end)
- );
-
- // Swap links
- edgeBefore1.next.prev = newEdge2;
- newEdge2.next = edgeBefore1.next;
-
- edgeBefore1.next = newEdge1;
- newEdge1.prev = edgeBefore1;
-
- edgeBefore2.next.prev = newEdge1;
- newEdge1.next = edgeBefore2.next;
-
- edgeBefore2.next = newEdge2;
- newEdge2.prev = edgeBefore2;
-
- // Insert new edge to the edges container and 2d index
- this.edges.add(newEdge1);
- this.edges.add(newEdge2);
-
- // Add two new faces
- let face1 = this.addFace(newEdge1, edgeBefore1);
- let face2 = this.addFace(newEdge2, edgeBefore2);
-
- // Remove old face
- this.faces.delete(face);
-
- return [face1.toPolygon(), face2.toPolygon()];
- }
-
- /**
- * Return a result of cutting polygon with line
- * @param {Line} line - cutting line
- * @returns {Polygon} newPoly - resulted polygon
- */
- cutWithLine(line) {
- let newPoly = this.clone();
-
- let multiline = new Multiline([line]);
+ let newPoly = this.clone()
// smart intersections
let intersections = {
@@ -432,14 +347,16 @@ classes/polygon.js
int_points2_sorted: []
};
- // intersect line with each edge of the polygon
+ // intersect each edge of multiline with each edge of the polygon
// and create smart intersections
- for (let edge of newPoly.edges) {
- let ip = intersectEdge2Line(edge, line);
- // for each intersection point
- for (let pt of ip) {
- addToIntPoints(multiline.first, pt, intersections.int_points1);
- addToIntPoints(edge, pt, intersections.int_points2);
+ for (let edge1 of multiline.edges) {
+ for (let edge2 of newPoly.edges) {
+ let ip = intersectEdge2Edge(edge1, edge2);
+ // for each intersection point
+ for (let pt of ip) {
+ addToIntPoints(edge1, pt, intersections.int_points1);
+ addToIntPoints(edge2, pt, intersections.int_points2);
+ }
}
}
@@ -448,7 +365,7 @@ classes/polygon.js
return newPoly;
// sort smart intersections
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// split by intersection points
@@ -459,7 +376,7 @@ classes/polygon.js
filterDuplicatedIntersections(intersections);
// sort intersection points again after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
// initialize inclusion flags for edges of multiline incident to intersections
@@ -470,7 +387,8 @@ classes/polygon.js
// filter intersections between two edges that got same inclusion flag
for (let int_point1 of intersections.int_points1_sorted) {
- if (int_point1.edge_before.bv === int_point1.edge_after.bv) {
+ if (int_point1.edge_before && int_point1.edge_after &&
+ int_point1.edge_before.bv === int_point1.edge_after.bv) {
intersections.int_points2[int_point1.id] = -1; // to be filtered out
int_point1.id = -1; // to be filtered out
}
@@ -483,28 +401,48 @@ classes/polygon.js
return newPoly;
// sort intersection points 3d time after filtering
- intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1);
+ intersections.int_points1_sorted = getSortedArray(intersections.int_points1);
intersections.int_points2_sorted = getSortedArray(intersections.int_points2);
- // Add 2 new inner edges between intersection points
- let int_point1_prev = intersections.int_points1[0];
- let new_edge;
- for (let int_point1_curr of intersections.int_points1_sorted) {
- if (int_point1_curr.edge_before.bv === INSIDE) {
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape);
- insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge);
- newPoly.edges.add(new_edge);
-
- new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse());
- insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge);
- newPoly.edges.add(new_edge);
+ // Add new inner edges between intersection points
+ let int_point1_prev
+ let int_point1_curr;
+ for (let i = 1; i < intersections.int_points1_sorted.length; i++) {
+ int_point1_curr = intersections.int_points1_sorted[i]
+ int_point1_prev = intersections.int_points1_sorted[i-1];
+ if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) {
+ let edgeFrom = int_point1_prev.edge_after
+ let edgeTo = int_point1_curr.edge_before
+ let newEdges = multiline.getChain(edgeFrom, edgeTo)
+ insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge))
+
+ newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse()))
+ for (let k=0; k < newEdges.length-1; k++) {
+ newEdges[k].next = newEdges[k+1]
+ newEdges[k+1].prev = newEdges[k]
+ }
+ insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges);
+ newEdges.forEach(edge => newPoly.edges.add(edge));
}
- int_point1_prev = int_point1_curr;
+
}
// Recreate faces
newPoly.recreateFaces();
- return newPoly;
+
+ return newPoly
+ }
+
+ /**
+ * A special case of cut() function
+ * The return is a polygon cut with line
+ * @param {Line} line - cutting line
+ * @returns {Polygon} newPoly - resulted polygon
+ */
+ cutWithLine(line) {
+ let multiline = new Multiline([line]);
+ return this.cut(multiline);
}
/**
@@ -524,8 +462,8 @@ classes/polygon.js
}
/**
- * Split polygon into array of polygons, where each polygon is an island with all
- * hole that it contains
+ * Split polygon into array of polygons, where each polygon is an outer face with all
+ * containing inner faces
* @returns {Flatten.Polygon[]}
*/
splitToIslands() {
@@ -762,7 +700,7 @@ classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html
index 21d8f25..6ef5d79 100644
--- a/docs/classes_ray.js.html
+++ b/docs/classes_ray.js.html
@@ -24,7 +24,7 @@
@@ -45,6 +45,7 @@ classes/ray.js
import * as Intersection from "../algorithms/intersection";
import {Shape} from "./shape";
import {Errors} from "../utils/errors";
+import {vector} from './vector'
/**
* Class representing a ray (a half-infinite line).
@@ -152,6 +153,18 @@ classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0);
}
+ /**
+ * Return coordinate of the point that lies on the ray in the transformed
+ * coordinate system where center is the projection of the point(0,0) to
+ * the line containing this ray and axe y is collinear to the normal vector. <br/>
+ * This method assumes that point lies on the ray
+ * @param {Point} pt - point on a ray
+ * @returns {number}
+ */
+ coord(pt) {
+ return vector(pt.x, pt.y).cross(this.norm);
+ }
+
/**
* Split ray with point and return array of segment and new ray
* @param {Point} pt
@@ -271,7 +284,7 @@ classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html
index 9e251cb..149f7b1 100644
--- a/docs/classes_segment.js.html
+++ b/docs/classes_segment.js.html
@@ -24,7 +24,7 @@
@@ -420,7 +420,7 @@ classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html
index c633850..b94b6b7 100644
--- a/docs/classes_shape.js.html
+++ b/docs/classes_shape.js.html
@@ -24,7 +24,7 @@
@@ -122,7 +122,7 @@ classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html
index 6f7e7b0..3e7f891 100644
--- a/docs/classes_vector.js.html
+++ b/docs/classes_vector.js.html
@@ -24,7 +24,7 @@
@@ -311,7 +311,7 @@ classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html
index 2628ea3..a44299b 100644
--- a/docs/data_structures_circular_linked_list.js.html
+++ b/docs/data_structures_circular_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -117,7 +117,7 @@ data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html
index 8b717c8..65ee662 100644
--- a/docs/data_structures_de9im.js.html
+++ b/docs/data_structures_de9im.js.html
@@ -24,7 +24,7 @@
@@ -262,7 +262,7 @@ data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html
index c0d1d21..01eec6c 100644
--- a/docs/data_structures_linked_list.js.html
+++ b/docs/data_structures_linked_list.js.html
@@ -24,7 +24,7 @@
@@ -215,7 +215,7 @@ data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html
index 307fba1..cee942d 100644
--- a/docs/data_structures_planar_set.js.html
+++ b/docs/data_structures_planar_set.js.html
@@ -24,7 +24,7 @@
@@ -156,7 +156,7 @@ data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html
index 1d7c411..9864a64 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -24,7 +24,7 @@
@@ -761,7 +761,7 @@ (constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
Returns:
diff --git a/docs/Segment.html b/docs/Segment.html index 221eb70..2964cc6 100644 --- a/docs/Segment.html +++ b/docs/Segment.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/Shape.html b/docs/Shape.html index 83a9934..77269d1 100644 --- a/docs/Shape.html +++ b/docs/Shape.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/Vector.html b/docs/Vector.html index 65000b7..51d652d 100644 --- a/docs/Vector.html +++ b/docs/Vector.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/algorithms_boolean_op.js.html b/docs/algorithms_boolean_op.js.html index 5f2cf51..a29035f 100644 --- a/docs/algorithms_boolean_op.js.html +++ b/docs/algorithms_boolean_op.js.html @@ -24,7 +24,7 @@
algorithms/boolean_op.js
diff --git a/docs/algorithms_distance.js.html b/docs/algorithms_distance.js.html index d61b05b..6f81dbe 100644 --- a/docs/algorithms_distance.js.html +++ b/docs/algorithms_distance.js.html @@ -24,7 +24,7 @@
algorithms/distance.js
diff --git a/docs/algorithms_ray_shooting.js.html b/docs/algorithms_ray_shooting.js.html index 61e578d..6bcc0a9 100644 --- a/docs/algorithms_ray_shooting.js.html +++ b/docs/algorithms_ray_shooting.js.html @@ -24,7 +24,7 @@
algorithms/ray_shooting.js
diff --git a/docs/algorithms_relation.js.html b/docs/algorithms_relation.js.html index 41856b7..b93034d 100644 --- a/docs/algorithms_relation.js.html +++ b/docs/algorithms_relation.js.html @@ -24,7 +24,7 @@
algorithms/relation.js
denim.I2B = ip_sorted; denim.I2E = [splitShapes[0], splitShapes[2]]; - denim.E2I = new Flatten.Polygon([circle.toArc()]).cut(multiline); + denim.E2I = new Flatten.Polygon([circle.toArc()]).cutWithLine(line); } return denim; @@ -286,7 +286,7 @@algorithms/relation.js
denim.I2B = ip_sorted; denim.I2E = [splitShapes[0], splitShapes[2]]; - denim.E2I = new Flatten.Polygon(box.toSegments()).cut(multiline); + denim.E2I = new Flatten.Polygon(box.toSegments()).cutWithLine(line); } } return denim; @@ -306,7 +306,7 @@algorithms/relation.js
denim.I2B = [...multiline].slice(1).map( (edge) => edge.bv === Flatten.BOUNDARY ? edge.shape : edge.shape.start ); denim.I2E = [...multiline].filter(edge => edge.bv === Flatten.OUTSIDE).map(edge => edge.shape); - denim.E2I = polygon.cut(multiline); + denim.E2I = polygon.cutWithLine(line); return denim; } @@ -387,7 +387,7 @@algorithms/relation.js
diff --git a/docs/classes_arc.js.html b/docs/classes_arc.js.html index 03bb7c9..5848b6f 100644 --- a/docs/classes_arc.js.html +++ b/docs/classes_arc.js.html @@ -24,7 +24,7 @@
classes/arc.js
diff --git a/docs/classes_box.js.html b/docs/classes_box.js.html index 477a6d7..002303e 100644 --- a/docs/classes_box.js.html +++ b/docs/classes_box.js.html @@ -24,7 +24,7 @@
classes/box.js
diff --git a/docs/classes_circle.js.html b/docs/classes_circle.js.html index 55d4975..456044a 100644 --- a/docs/classes_circle.js.html +++ b/docs/classes_circle.js.html @@ -24,7 +24,7 @@
classes/circle.js
diff --git a/docs/classes_edge.js.html b/docs/classes_edge.js.html index 447d634..3f037b1 100644 --- a/docs/classes_edge.js.html +++ b/docs/classes_edge.js.html @@ -24,7 +24,7 @@
classes/edge.js
return this.shape.box; } - isSegment() { + get isSegment() { return this.shape instanceof Flatten.Segment; } - isArc() { + get isArc() { return this.shape instanceof Flatten.Arc; } + get isLine() { + return this.shape instanceof Flatten.Line; + } + + get isRay() { + return this.shape instanceof Flatten.Ray + } + /** * Get middle point of the edge * @returns {Point} @@ -286,7 +294,7 @@classes/edge.js
diff --git a/docs/classes_face.js.html b/docs/classes_face.js.html index b42bed7..e3b4680 100644 --- a/docs/classes_face.js.html +++ b/docs/classes_face.js.html @@ -24,7 +24,7 @@
classes/face.js
diff --git a/docs/classes_inversion.js.html b/docs/classes_inversion.js.html index f46dd6a..0a5920e 100644 --- a/docs/classes_inversion.js.html +++ b/docs/classes_inversion.js.html @@ -24,7 +24,7 @@
classes/inversion.js
diff --git a/docs/classes_line.js.html b/docs/classes_line.js.html index 97331f9..82b4e7e 100644 --- a/docs/classes_line.js.html +++ b/docs/classes_line.js.html @@ -24,7 +24,7 @@
classes/line.js
*/ split(pt) { if (pt instanceof Flatten.Point) { - return [new Flatten.Ray(pt, this.norm.invert()), new Flatten.Ray(pt, this.norm)] + return [new Flatten.Ray(pt, this.norm), new Flatten.Ray(pt, this.norm)] } else { let multiline = new Flatten.Multiline([this]); @@ -425,7 +425,7 @@classes/line.js
diff --git a/docs/classes_matrix.js.html b/docs/classes_matrix.js.html index bb53e6b..dbd2709 100644 --- a/docs/classes_matrix.js.html +++ b/docs/classes_matrix.js.html @@ -24,7 +24,7 @@
classes/matrix.js
diff --git a/docs/classes_multiline.js.html b/docs/classes_multiline.js.html index 1948655..66d46f5 100644 --- a/docs/classes_multiline.js.html +++ b/docs/classes_multiline.js.html @@ -24,7 +24,7 @@
classes/multiline.js
import Flatten from '../flatten'; import LinkedList from '../data_structures/linked_list'; -import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants"; import {convertToString} from "../utils/attributes"; /** @@ -58,10 +57,10 @@classes/multiline.js
return; } - if (args.length == 1) { + if (args.length === 1) { if (args[0] instanceof Array) { let shapes = args[0]; - if (shapes.length == 0) + if (shapes.length === 0) return; // TODO: more strict validation: @@ -78,6 +77,8 @@classes/multiline.js
let edge = new Flatten.Edge(shape); this.append(edge); } + + this.setArcLength() } } } @@ -95,7 +96,7 @@classes/multiline.js
* @returns {Box} */ get box() { - return this.edges.reduce( (acc,edge) => acc = acc.merge(edge.box), new Flatten.Box() ); + return this.edges.reduce( (acc,edge) => acc.merge(edge.box), new Flatten.Box() ); } /** @@ -116,6 +117,24 @@classes/multiline.js
return new Multiline(this.toShapes()); } + /** + * Set arc_length property for each of the edges in the face. + * Arc_length of the edge it the arc length from the first edge of the face + */ + setArcLength() { + for (let edge of this) { + this.setOneEdgeArcLength(edge); + } + } + + setOneEdgeArcLength(edge) { + if (edge === this.first) { + edge.arc_length = 0.0; + } else { + edge.arc_length = edge.prev.arc_length + edge.prev.length; + } + } + /** * Split edge and add new vertex, return new edge inserted * @param {Point} pt - point on edge that will be added as new vertex @@ -144,6 +163,14 @@classes/multiline.js
return newEdge; } + getChain(edgeFrom, edgeTo) { + let edges = [] + for (let edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) { + edges.push(edge) + } + return edges + } + /** * Split edges of multiline with intersection points and return mutated multiline * @param {Point[]} ip - array of points to be added as new vertices @@ -258,7 +285,7 @@classes/multiline.js
diff --git a/docs/classes_point.js.html b/docs/classes_point.js.html index 48602f2..6923f55 100644 --- a/docs/classes_point.js.html +++ b/docs/classes_point.js.html @@ -24,7 +24,7 @@
classes/point.js
diff --git a/docs/classes_polygon.js.html b/docs/classes_polygon.js.html index 423a9c6..017e282 100644 --- a/docs/classes_polygon.js.html +++ b/docs/classes_polygon.js.html @@ -24,7 +24,7 @@
classes/polygon.js
import * as Relations from "../algorithms/relation"; import { addToIntPoints, calculateInclusionFlags, filterDuplicatedIntersections, - getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints, + getSortedArray, initializeInclusionFlags, insertBetweenIntPoints, splitByIntersections } from "../data_structures/smart_intersections"; import {Multiline} from "./multiline"; -import {intersectEdge2Line} from "../algorithms/intersection"; +import {intersectEdge2Edge} from "../algorithms/intersection"; import {INSIDE, BOUNDARY} from "../utils/constants"; import {convertToString} from "../utils/attributes"; import {Matrix} from "./matrix"; @@ -332,97 +332,12 @@classes/polygon.js
} /** - * Cut polygon with multiline and return array of new polygons - * Multiline should be constructed from a line with intersection point, see notebook: - * https://next.observablehq.com/@alexbol99/cut-polygon-with-line + * Cut polygon with multiline and return a new polygon * @param {Multiline} multiline - * @returns {Polygon[]} + * @returns {Polygon} */ cut(multiline) { - let cutPolygons = [this.clone()]; - for (let edge of multiline) { - if (edge.setInclusion(this) !== INSIDE) - continue; - - let cut_edge_start = edge.shape.start; - let cut_edge_end = edge.shape.end; - - let newCutPolygons = []; - for (let polygon of cutPolygons) { - if (polygon.findEdgeByPoint(cut_edge_start) === undefined) { - newCutPolygons.push(polygon); - } else { - let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end); - newCutPolygons.push(cutPoly1, cutPoly2); - } - } - cutPolygons = newCutPolygons; - } - return cutPolygons; - } - - /** - * Cut face of polygon with a segment between two points and create two new polygons - * Supposed that a segments between points does not intersect any other edge - * @param {Point} pt1 - * @param {Point} pt2 - * @returns {Polygon[]} - */ - cutFace(pt1, pt2) { - let edge1 = this.findEdgeByPoint(pt1); - let edge2 = this.findEdgeByPoint(pt2); - if (edge1.face !== edge2.face) - return []; - - // Cut face into two and create new polygon with two faces - let edgeBefore1 = this.addVertex(pt1, edge1); - edge2 = this.findEdgeByPoint(pt2); - let edgeBefore2 = this.addVertex(pt2, edge2); - - let face = edgeBefore1.face; - let newEdge1 = new Flatten.Edge( - new Flatten.Segment(edgeBefore1.end, edgeBefore2.end) - ); - let newEdge2 = new Flatten.Edge( - new Flatten.Segment(edgeBefore2.end, edgeBefore1.end) - ); - - // Swap links - edgeBefore1.next.prev = newEdge2; - newEdge2.next = edgeBefore1.next; - - edgeBefore1.next = newEdge1; - newEdge1.prev = edgeBefore1; - - edgeBefore2.next.prev = newEdge1; - newEdge1.next = edgeBefore2.next; - - edgeBefore2.next = newEdge2; - newEdge2.prev = edgeBefore2; - - // Insert new edge to the edges container and 2d index - this.edges.add(newEdge1); - this.edges.add(newEdge2); - - // Add two new faces - let face1 = this.addFace(newEdge1, edgeBefore1); - let face2 = this.addFace(newEdge2, edgeBefore2); - - // Remove old face - this.faces.delete(face); - - return [face1.toPolygon(), face2.toPolygon()]; - } - - /** - * Return a result of cutting polygon with line - * @param {Line} line - cutting line - * @returns {Polygon} newPoly - resulted polygon - */ - cutWithLine(line) { - let newPoly = this.clone(); - - let multiline = new Multiline([line]); + let newPoly = this.clone() // smart intersections let intersections = { @@ -432,14 +347,16 @@classes/polygon.js
int_points2_sorted: [] }; - // intersect line with each edge of the polygon + // intersect each edge of multiline with each edge of the polygon // and create smart intersections - for (let edge of newPoly.edges) { - let ip = intersectEdge2Line(edge, line); - // for each intersection point - for (let pt of ip) { - addToIntPoints(multiline.first, pt, intersections.int_points1); - addToIntPoints(edge, pt, intersections.int_points2); + for (let edge1 of multiline.edges) { + for (let edge2 of newPoly.edges) { + let ip = intersectEdge2Edge(edge1, edge2); + // for each intersection point + for (let pt of ip) { + addToIntPoints(edge1, pt, intersections.int_points1); + addToIntPoints(edge2, pt, intersections.int_points2); + } } } @@ -448,7 +365,7 @@classes/polygon.js
return newPoly; // sort smart intersections - intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1); + intersections.int_points1_sorted = getSortedArray(intersections.int_points1); intersections.int_points2_sorted = getSortedArray(intersections.int_points2); // split by intersection points @@ -459,7 +376,7 @@classes/polygon.js
filterDuplicatedIntersections(intersections); // sort intersection points again after filtering - intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1); + intersections.int_points1_sorted = getSortedArray(intersections.int_points1); intersections.int_points2_sorted = getSortedArray(intersections.int_points2); // initialize inclusion flags for edges of multiline incident to intersections @@ -470,7 +387,8 @@classes/polygon.js
// filter intersections between two edges that got same inclusion flag for (let int_point1 of intersections.int_points1_sorted) { - if (int_point1.edge_before.bv === int_point1.edge_after.bv) { + if (int_point1.edge_before && int_point1.edge_after && + int_point1.edge_before.bv === int_point1.edge_after.bv) { intersections.int_points2[int_point1.id] = -1; // to be filtered out int_point1.id = -1; // to be filtered out } @@ -483,28 +401,48 @@classes/polygon.js
return newPoly; // sort intersection points 3d time after filtering - intersections.int_points1_sorted = getSortedArrayOnLine(line, intersections.int_points1); + intersections.int_points1_sorted = getSortedArray(intersections.int_points1); intersections.int_points2_sorted = getSortedArray(intersections.int_points2); - // Add 2 new inner edges between intersection points - let int_point1_prev = intersections.int_points1[0]; - let new_edge; - for (let int_point1_curr of intersections.int_points1_sorted) { - if (int_point1_curr.edge_before.bv === INSIDE) { - new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_prev.pt, int_point1_curr.pt)); // (int_point1_curr.edge_before.shape); - insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge); - newPoly.edges.add(new_edge); - - new_edge = new Flatten.Edge(new Flatten.Segment(int_point1_curr.pt, int_point1_prev.pt)); // (int_point1_curr.edge_before.shape.reverse()); - insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge); - newPoly.edges.add(new_edge); + // Add new inner edges between intersection points + let int_point1_prev + let int_point1_curr; + for (let i = 1; i < intersections.int_points1_sorted.length; i++) { + int_point1_curr = intersections.int_points1_sorted[i] + int_point1_prev = intersections.int_points1_sorted[i-1]; + if (int_point1_curr.edge_before && int_point1_curr.edge_before.bv === INSIDE) { + let edgeFrom = int_point1_prev.edge_after + let edgeTo = int_point1_curr.edge_before + let newEdges = multiline.getChain(edgeFrom, edgeTo) + insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], newEdges); + newEdges.forEach(edge => newPoly.edges.add(edge)) + + newEdges = newEdges.reverse().map(edge => new Flatten.Edge(edge.shape.reverse())) + for (let k=0; k < newEdges.length-1; k++) { + newEdges[k].next = newEdges[k+1] + newEdges[k+1].prev = newEdges[k] + } + insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], newEdges); + newEdges.forEach(edge => newPoly.edges.add(edge)); } - int_point1_prev = int_point1_curr; + } // Recreate faces newPoly.recreateFaces(); - return newPoly; + + return newPoly + } + + /** + * A special case of cut() function + * The return is a polygon cut with line + * @param {Line} line - cutting line + * @returns {Polygon} newPoly - resulted polygon + */ + cutWithLine(line) { + let multiline = new Multiline([line]); + return this.cut(multiline); } /** @@ -524,8 +462,8 @@classes/polygon.js
} /** - * Split polygon into array of polygons, where each polygon is an island with all - * hole that it contains + * Split polygon into array of polygons, where each polygon is an outer face with all + * containing inner faces * @returns {Flatten.Polygon[]} */ splitToIslands() { @@ -762,7 +700,7 @@classes/polygon.js
diff --git a/docs/classes_ray.js.html b/docs/classes_ray.js.html index 21d8f25..6ef5d79 100644 --- a/docs/classes_ray.js.html +++ b/docs/classes_ray.js.html @@ -24,7 +24,7 @@
classes/ray.js
import * as Intersection from "../algorithms/intersection"; import {Shape} from "./shape"; import {Errors} from "../utils/errors"; +import {vector} from './vector' /** * Class representing a ray (a half-infinite line). @@ -152,6 +153,18 @@classes/ray.js
return Flatten.Utils.EQ_0(this.norm.dot(vec)) && Flatten.Utils.GE(vec.cross(this.norm),0); } + /** + * Return coordinate of the point that lies on the ray in the transformed + * coordinate system where center is the projection of the point(0,0) to + * the line containing this ray and axe y is collinear to the normal vector. <br/> + * This method assumes that point lies on the ray + * @param {Point} pt - point on a ray + * @returns {number} + */ + coord(pt) { + return vector(pt.x, pt.y).cross(this.norm); + } + /** * Split ray with point and return array of segment and new ray * @param {Point} pt @@ -271,7 +284,7 @@classes/ray.js
diff --git a/docs/classes_segment.js.html b/docs/classes_segment.js.html index 9e251cb..149f7b1 100644 --- a/docs/classes_segment.js.html +++ b/docs/classes_segment.js.html @@ -24,7 +24,7 @@
classes/segment.js
diff --git a/docs/classes_shape.js.html b/docs/classes_shape.js.html index c633850..b94b6b7 100644 --- a/docs/classes_shape.js.html +++ b/docs/classes_shape.js.html @@ -24,7 +24,7 @@
classes/shape.js
diff --git a/docs/classes_vector.js.html b/docs/classes_vector.js.html index 6f7e7b0..3e7f891 100644 --- a/docs/classes_vector.js.html +++ b/docs/classes_vector.js.html @@ -24,7 +24,7 @@
classes/vector.js
diff --git a/docs/data_structures_circular_linked_list.js.html b/docs/data_structures_circular_linked_list.js.html index 2628ea3..a44299b 100644 --- a/docs/data_structures_circular_linked_list.js.html +++ b/docs/data_structures_circular_linked_list.js.html @@ -24,7 +24,7 @@
data_structures/circular_linked_list.js
diff --git a/docs/data_structures_de9im.js.html b/docs/data_structures_de9im.js.html index 8b717c8..65ee662 100644 --- a/docs/data_structures_de9im.js.html +++ b/docs/data_structures_de9im.js.html @@ -24,7 +24,7 @@
data_structures/de9im.js
diff --git a/docs/data_structures_linked_list.js.html b/docs/data_structures_linked_list.js.html index c0d1d21..01eec6c 100644 --- a/docs/data_structures_linked_list.js.html +++ b/docs/data_structures_linked_list.js.html @@ -24,7 +24,7 @@
data_structures/linked_list.js
diff --git a/docs/data_structures_planar_set.js.html b/docs/data_structures_planar_set.js.html index 307fba1..cee942d 100644 --- a/docs/data_structures_planar_set.js.html +++ b/docs/data_structures_planar_set.js.html @@ -24,7 +24,7 @@
data_structures/planar_set.js
diff --git a/docs/global.html b/docs/global.html index 1d7c411..9864a64 100644 --- a/docs/global.html +++ b/docs/global.html @@ -24,7 +24,7 @@
(constant) m
(constant) pol
Parameters:
diff --git a/docs/index.html b/docs/index.html
index 2188a7e..a0029da 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -24,7 +24,7 @@
@@ -341,7 +341,7 @@ Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html
index 2bf8168..41d8ae7 100644
--- a/docs/module-BooleanOperations.html
+++ b/docs/module-BooleanOperations.html
@@ -24,7 +24,7 @@
@@ -1185,7 +1185,7 @@ Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html
index 9ed5637..ee64a3d 100644
--- a/docs/module-RayShoot.html
+++ b/docs/module-RayShoot.html
@@ -24,7 +24,7 @@
@@ -275,7 +275,7 @@ Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html
index 5a910e7..443dc8d 100644
--- a/docs/module-Relation.html
+++ b/docs/module-Relation.html
@@ -24,7 +24,7 @@
@@ -1641,7 +1641,7 @@ Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html
index 5503d17..b0cfeea 100644
--- a/docs/utils_constants.js.html
+++ b/docs/utils_constants.js.html
@@ -24,7 +24,7 @@
@@ -85,7 +85,7 @@ utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html
index 075b96d..4d54a76 100644
--- a/docs/utils_errors.js.html
+++ b/docs/utils_errors.js.html
@@ -24,7 +24,7 @@
@@ -108,7 +108,7 @@ utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html
index 10a5909..351414b 100644
--- a/docs/utils_utils.js.html
+++ b/docs/utils_utils.js.html
@@ -24,7 +24,7 @@
@@ -135,7 +135,7 @@ utils/utils.js
diff --git a/index.js b/index.js
index 4d7082c..dba0e5a 100644
--- a/index.js
+++ b/index.js
@@ -34,6 +34,6 @@ export {SmartIntersections};
Flatten.BooleanOperations = BooleanOperations;
Flatten.Relations = Relations;
-export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants';
+export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants';
export default Flatten;
diff --git a/package.json b/package.json
index 01eb053..47067db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flatten-js/core",
- "version": "1.4.8",
+ "version": "1.5.0",
"description": "Javascript library for 2d geometry",
"main": "dist/main.cjs",
"umd:main": "dist/main.umd.js",
Parameters:
diff --git a/docs/index.html b/docs/index.html index 2188a7e..a0029da 100644 --- a/docs/index.html +++ b/docs/index.html @@ -24,7 +24,7 @@
Support
diff --git a/docs/module-BooleanOperations.html b/docs/module-BooleanOperations.html index 2bf8168..41d8ae7 100644 --- a/docs/module-BooleanOperations.html +++ b/docs/module-BooleanOperations.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/module-RayShoot.html b/docs/module-RayShoot.html index 9ed5637..ee64a3d 100644 --- a/docs/module-RayShoot.html +++ b/docs/module-RayShoot.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/module-Relation.html b/docs/module-Relation.html index 5a910e7..443dc8d 100644 --- a/docs/module-Relation.html +++ b/docs/module-Relation.html @@ -24,7 +24,7 @@
Returns:
diff --git a/docs/utils_constants.js.html b/docs/utils_constants.js.html index 5503d17..b0cfeea 100644 --- a/docs/utils_constants.js.html +++ b/docs/utils_constants.js.html @@ -24,7 +24,7 @@
utils/constants.js
diff --git a/docs/utils_errors.js.html b/docs/utils_errors.js.html index 075b96d..4d54a76 100644 --- a/docs/utils_errors.js.html +++ b/docs/utils_errors.js.html @@ -24,7 +24,7 @@
utils/errors.js
diff --git a/docs/utils_utils.js.html b/docs/utils_utils.js.html index 10a5909..351414b 100644 --- a/docs/utils_utils.js.html +++ b/docs/utils_utils.js.html @@ -24,7 +24,7 @@
utils/utils.js
diff --git a/index.js b/index.js index 4d7082c..dba0e5a 100644 --- a/index.js +++ b/index.js @@ -34,6 +34,6 @@ export {SmartIntersections}; Flatten.BooleanOperations = BooleanOperations; Flatten.Relations = Relations; -export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY} from './src/utils/constants'; +export {CCW, CW, ORIENTATION, INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} from './src/utils/constants'; export default Flatten; diff --git a/package.json b/package.json index 01eb053..47067db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@flatten-js/core", - "version": "1.4.8", + "version": "1.5.0", "description": "Javascript library for 2d geometry", "main": "dist/main.cjs", "umd:main": "dist/main.umd.js",