@flatten-js/core
Advanced tools
Comparing version 1.3.1 to 1.3.2
@@ -0,0 +0,0 @@ { |
@@ -0,0 +0,0 @@ /*global document */ |
@@ -0,0 +0,0 @@ |
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", | ||
/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); |
@@ -0,0 +0,0 @@ var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; |
@@ -0,0 +0,0 @@ { |
@@ -499,2 +499,3 @@ // Type definitions for flatten-js library | ||
deleteFace(face: Face): boolean; | ||
recreateFaces(): void; | ||
removeChain(face: Face, edgeFrom: PolygonEdge, edgeTo: PolygonEdge): void; | ||
@@ -504,2 +505,3 @@ addVertex(pt: Point, edge: PolygonEdge): PolygonEdge; | ||
cutFace(pt1: Point, pt2: Point): [Polygon, Polygon]; | ||
cutWithLine(line: Line): Polygon; | ||
findEdgeByPoint(pt: Point): PolygonEdge; | ||
@@ -506,0 +508,0 @@ splitToIslands() : Polygon[]; |
{ | ||
"name": "@flatten-js/core", | ||
"version": "1.3.1", | ||
"version": "1.3.2", | ||
"description": "Javascript library for 2d geometry", | ||
@@ -5,0 +5,0 @@ "main": "dist/main.cjs.js", |
@@ -9,11 +9,12 @@ /** | ||
import Flatten from '../flatten'; | ||
import * as Utils from '../utils/utils'; | ||
import Errors from "../utils/errors"; | ||
import * as Constants from '../utils/constants'; | ||
import LinkedList from "../data_structures/linked_list"; | ||
import {addToIntPoints, sortIntersections, | ||
filterDuplicatedIntersections, initializeInclusionFlags, | ||
setOverlappingFlags, intPointsPoolCount, splitByIntersections} from "../data_structures/smart_intersections"; | ||
let {INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} = Flatten; | ||
const {INSIDE, OUTSIDE, BOUNDARY, OVERLAP_SAME, OVERLAP_OPPOSITE} = Constants; | ||
const {NOT_VERTEX, START_VERTEX, END_VERTEX} = Constants; | ||
const NOT_VERTEX = 0; | ||
const START_VERTEX = 1; | ||
const END_VERTEX = 2; | ||
export const BOOLEAN_UNION = 1; | ||
@@ -52,3 +53,3 @@ export const BOOLEAN_INTERSECT = 2; | ||
* Intersect two polygons and returns new polygon | ||
* Point belongs to the resultes polygon is it belongs to the first AND to the second polygon | ||
* Point belongs to the resulted polygon is it belongs to the first AND to the second polygon | ||
* @param {Polygon} polygon1 - first operand | ||
@@ -244,209 +245,2 @@ * @param {Polygon} polygon2 - second operand | ||
export function addToIntPoints(edge, pt, int_points) | ||
{ | ||
let id = int_points.length; | ||
let shapes = edge.shape.split(pt); | ||
// if (shapes.length < 2) return; | ||
if (shapes.length === 0) return; // Point does not belong to edge ? | ||
let len = 0; | ||
if (shapes[0] === null) { // point incident to edge start vertex | ||
len = 0; | ||
} | ||
else if (shapes[1] === null) { // point incident to edge end vertex | ||
len = edge.shape.length; | ||
} | ||
else { // Edge was split into to edges | ||
len = shapes[0].length; | ||
} | ||
let is_vertex = NOT_VERTEX; | ||
if (Utils.EQ(len, 0)) { | ||
is_vertex |= START_VERTEX; | ||
} | ||
if (Utils.EQ(len, edge.shape.length)) { | ||
is_vertex |= END_VERTEX; | ||
} | ||
// Fix intersection point which is end point of the last edge | ||
let arc_length = (is_vertex & END_VERTEX) && edge.next.arc_length === 0 ? 0 : edge.arc_length + len; | ||
int_points.push({ | ||
id: id, | ||
pt: pt, | ||
arc_length: arc_length, | ||
edge_before: edge, | ||
edge_after: undefined, | ||
face: edge.face, | ||
is_vertex: is_vertex | ||
}); | ||
} | ||
function sortIntersections(intersections) | ||
{ | ||
// if (intersections.int_points1.length === 0) return; | ||
// augment intersections with new sorted arrays | ||
// intersections.int_points1_sorted = intersections.int_points1.slice().sort(compareFn); | ||
// intersections.int_points2_sorted = intersections.int_points2.slice().sort(compareFn); | ||
intersections.int_points1_sorted = getSortedArray(intersections.int_points1); | ||
intersections.int_points2_sorted = getSortedArray(intersections.int_points2); | ||
} | ||
export function getSortedArray(int_points) | ||
{ | ||
let faceMap = new Map; | ||
let id = 0; | ||
// Create integer id's for faces | ||
for (let ip of int_points) { | ||
if (!faceMap.has(ip.face)) { | ||
faceMap.set(ip.face, id); | ||
id++; | ||
} | ||
} | ||
// Augment intersection points with face id's | ||
for (let ip of int_points) { | ||
ip.faceId = faceMap.get(ip.face); | ||
} | ||
// Clone and sort | ||
let int_points_sorted = int_points.slice().sort(compareFn); | ||
return int_points_sorted; | ||
} | ||
function compareFn(ip1, ip2) | ||
{ | ||
// compare face id's | ||
if (ip1.faceId < ip2.faceId) { | ||
return -1; | ||
} | ||
if (ip1.faceId > ip2.faceId) { | ||
return 1; | ||
} | ||
// same face - compare arc_length | ||
if (ip1.arc_length < ip2.arc_length) { | ||
return -1; | ||
} | ||
if (ip1.arc_length > ip2.arc_length) { | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
export function splitByIntersections(polygon, int_points) | ||
{ | ||
if (!int_points) return; | ||
for (let int_point of int_points) { | ||
let edge = int_point.edge_before; | ||
// recalculate vertex flag: it may be changed after previous split | ||
int_point.is_vertex = NOT_VERTEX; | ||
if (edge.shape.start.equalTo(int_point.pt)) { | ||
int_point.is_vertex |= START_VERTEX; | ||
} | ||
if (edge.shape.end.equalTo(int_point.pt)) { | ||
int_point.is_vertex |= END_VERTEX; | ||
} | ||
if (int_point.is_vertex & START_VERTEX) { // nothing to split | ||
int_point.edge_before = edge.prev; | ||
int_point.is_vertex = END_VERTEX; | ||
continue; | ||
} | ||
if (int_point.is_vertex & END_VERTEX) { // nothing to split | ||
continue; | ||
} | ||
let newEdge = polygon.addVertex(int_point.pt, edge); | ||
int_point.edge_before = newEdge; | ||
} | ||
for (let int_point of int_points) { | ||
int_point.edge_after = int_point.edge_before.next; | ||
} | ||
} | ||
export function filterDuplicatedIntersections(intersections) | ||
{ | ||
if (intersections.int_points1.length < 2) return; | ||
let do_squeeze = false; | ||
let int_point_ref1; | ||
let int_point_ref2; | ||
let int_point_cur1; | ||
let int_point_cur2; | ||
for (let i = 0; i < intersections.int_points1_sorted.length; i++) { | ||
if (intersections.int_points1_sorted[i].id === -1) | ||
continue; | ||
int_point_ref1 = intersections.int_points1_sorted[i]; | ||
int_point_ref2 = intersections.int_points2[int_point_ref1.id]; | ||
for (let j=i+1; j < intersections.int_points1_sorted.length; j++) { | ||
int_point_cur1 = intersections.int_points1_sorted[j]; | ||
if (!Utils.EQ(int_point_cur1.arc_length, int_point_ref1.arc_length)) { | ||
break; | ||
} | ||
if (int_point_cur1.id === -1) | ||
continue; | ||
int_point_cur2 = intersections.int_points2[int_point_cur1.id]; | ||
if (int_point_cur2.id === -1) | ||
continue; | ||
if (int_point_cur1.edge_before === int_point_ref1.edge_before && | ||
int_point_cur1.edge_after === int_point_ref1.edge_after && | ||
int_point_cur2.edge_before === int_point_ref2.edge_before && | ||
int_point_cur2.edge_after === int_point_ref2.edge_after) { | ||
int_point_cur1.id = -1; | ||
/* to be deleted */ | ||
int_point_cur2.id = -1; | ||
/* to be deleted */ | ||
do_squeeze = true; | ||
} | ||
} | ||
} | ||
int_point_ref2 = intersections.int_points2_sorted[0]; | ||
int_point_ref1 = intersections.int_points1[int_point_ref2.id]; | ||
for (let i = 1; i < intersections.int_points2_sorted.length; i++) { | ||
let int_point_cur2 = intersections.int_points2_sorted[i]; | ||
if (int_point_cur2.id == -1) continue; | ||
/* already deleted */ | ||
if (int_point_ref2.id == -1 || /* can't be reference if already deleted */ | ||
!(Utils.EQ(int_point_cur2.arc_length, int_point_ref2.arc_length))) { | ||
int_point_ref2 = int_point_cur2; | ||
int_point_ref1 = intersections.int_points1[int_point_ref2.id]; | ||
continue; | ||
} | ||
let int_point_cur1 = intersections.int_points1[int_point_cur2.id]; | ||
if (int_point_cur1.edge_before === int_point_ref1.edge_before && | ||
int_point_cur1.edge_after === int_point_ref1.edge_after && | ||
int_point_cur2.edge_before === int_point_ref2.edge_before && | ||
int_point_cur2.edge_after === int_point_ref2.edge_after) { | ||
int_point_cur1.id = -1; | ||
/* to be deleted */ | ||
int_point_cur2.id = -1; | ||
/* to be deleted */ | ||
do_squeeze = true; | ||
} | ||
} | ||
if (do_squeeze) { | ||
intersections.int_points1 = intersections.int_points1.filter((int_point) => int_point.id >= 0); | ||
intersections.int_points2 = intersections.int_points2.filter((int_point) => int_point.id >= 0); | ||
// update id's | ||
intersections.int_points1.forEach((int_point, index) => int_point.id = index); | ||
intersections.int_points2.forEach((int_point, index) => int_point.id = index); | ||
// re-create sorted | ||
intersections.int_points1_sorted = []; | ||
intersections.int_points2_sorted = []; | ||
sortIntersections(intersections); | ||
} | ||
} | ||
function getNotIntersectedFaces(poly, int_points) | ||
@@ -471,22 +265,2 @@ { | ||
function initializeInclusionFlags(int_points) | ||
{ | ||
for (let int_point of int_points) { | ||
int_point.edge_before.bvStart = undefined; | ||
int_point.edge_before.bvEnd = undefined; | ||
int_point.edge_before.bv = undefined; | ||
int_point.edge_before.overlap = undefined; | ||
int_point.edge_after.bvStart = undefined; | ||
int_point.edge_after.bvEnd = undefined; | ||
int_point.edge_after.bv = undefined; | ||
int_point.edge_after.overlap = undefined; | ||
} | ||
for (let int_point of int_points) { | ||
int_point.edge_before.bvEnd = BOUNDARY; | ||
int_point.edge_after.bvStart = BOUNDARY; | ||
} | ||
} | ||
function calculateInclusionFlags(int_points, polygon) | ||
@@ -582,3 +356,3 @@ { | ||
if (edge_tmp.bv != new_bv) { // and it has different bv - can't resolve conflict | ||
throw Flatten.Errors.UNRESOLVED_BOUNDARY_CONFLICT; | ||
throw Errors.UNRESOLVED_BOUNDARY_CONFLICT; | ||
} | ||
@@ -685,3 +459,3 @@ } | ||
throw Flatten.Errors.UNRESOLVED_BOUNDARY_CONFLICT; | ||
throw Errors.UNRESOLVED_BOUNDARY_CONFLICT; | ||
} | ||
@@ -693,78 +467,2 @@ } | ||
function setOverlappingFlags(intersections) | ||
{ | ||
let cur_face = undefined; | ||
let first_int_point_in_face_id = undefined; | ||
let next_int_point1 = undefined; | ||
let num_int_points = intersections.int_points1.length; | ||
for (let i = 0; i < num_int_points; i++) { | ||
let cur_int_point1 = intersections.int_points1_sorted[i]; | ||
// Find boundary chain in the polygon1 | ||
if (cur_int_point1.face !== cur_face) { // next chain started | ||
first_int_point_in_face_id = i; // cur_int_point1; | ||
cur_face = cur_int_point1.face; | ||
} | ||
// Skip duplicated points with same <x,y> in "cur_int_point1" pool | ||
let int_points_cur_pool_start = i; | ||
let int_points_cur_pool_num = intPointsPoolCount(intersections.int_points1_sorted, i, cur_face); | ||
let next_int_point_id; | ||
if (int_points_cur_pool_start + int_points_cur_pool_num < num_int_points && | ||
intersections.int_points1_sorted[int_points_cur_pool_start + int_points_cur_pool_num].face === cur_face) { | ||
next_int_point_id = int_points_cur_pool_start + int_points_cur_pool_num; | ||
} else { // get first point from the same face | ||
next_int_point_id = first_int_point_in_face_id; | ||
} | ||
// From all points with same ,x,y. in 'next_int_point1' pool choose one that | ||
// has same face both in res_poly and in wrk_poly | ||
let int_points_next_pool_num = intPointsPoolCount(intersections.int_points1_sorted, next_int_point_id, cur_face); | ||
next_int_point1 = null; | ||
for (let j=next_int_point_id; j < next_int_point_id + int_points_next_pool_num; j++) { | ||
let next_int_point1_tmp = intersections.int_points1_sorted[j]; | ||
if (next_int_point1_tmp.face === cur_face && | ||
intersections.int_points2[next_int_point1_tmp.id].face === intersections.int_points2[cur_int_point1.id].face) { | ||
next_int_point1 = next_int_point1_tmp; | ||
break; | ||
} | ||
} | ||
if (next_int_point1 === null) | ||
continue; | ||
let edge_from1 = cur_int_point1.edge_after; | ||
let edge_to1 = next_int_point1.edge_before; | ||
if (!(edge_from1.bv === BOUNDARY && edge_to1.bv === BOUNDARY)) // not a boundary chain - skip | ||
continue; | ||
if (edge_from1 !== edge_to1) // one edge chain TODO: support complex case | ||
continue; | ||
/* Find boundary chain in polygon2 between same intersection points */ | ||
let cur_int_point2 = intersections.int_points2[cur_int_point1.id]; | ||
let next_int_point2 = intersections.int_points2[next_int_point1.id]; | ||
let edge_from2 = cur_int_point2.edge_after; | ||
let edge_to2 = next_int_point2.edge_before; | ||
/* if [edge_from2..edge_to2] is not a boundary chain, invert it */ | ||
/* check also that chain consist of one or two edges */ | ||
if (!(edge_from2.bv === BOUNDARY && edge_to2.bv === BOUNDARY && edge_from2 === edge_to2)) { | ||
cur_int_point2 = intersections.int_points2[next_int_point1.id]; | ||
next_int_point2 = intersections.int_points2[cur_int_point1.id]; | ||
edge_from2 = cur_int_point2.edge_after; | ||
edge_to2 = next_int_point2.edge_before; | ||
} | ||
if (!(edge_from2.bv === BOUNDARY && edge_to2.bv === BOUNDARY && edge_from2 === edge_to2)) | ||
continue; // not an overlapping chain - skip TODO: fix boundary conflict | ||
// Set overlapping flag - one-to-one case | ||
edge_from1.setOverlap(edge_from2); | ||
} | ||
} | ||
export function removeNotRelevantChains(polygon, op, int_points, is_res_polygon) | ||
@@ -836,31 +534,2 @@ { | ||
function intPointsPoolCount(int_points, cur_int_point_num, cur_face) | ||
{ | ||
let int_point_current; | ||
let int_point_next; | ||
let int_points_pool_num = 1; | ||
if (int_points.length == 1) return 1; | ||
int_point_current = int_points[cur_int_point_num]; | ||
for (let i = cur_int_point_num + 1; i < int_points.length; i++) { | ||
if (int_point_current.face != cur_face) { /* next face started */ | ||
break; | ||
} | ||
int_point_next = int_points[i]; | ||
if (!(int_point_next.pt.equalTo(int_point_current.pt) && | ||
int_point_next.edge_before === int_point_current.edge_before && | ||
int_point_next.edge_after === int_point_current.edge_after)) { | ||
break; /* next point is different - break and exit */ | ||
} | ||
int_points_pool_num++; /* duplicated intersection point - increase counter */ | ||
} | ||
return int_points_pool_num; | ||
} | ||
function copyWrkToRes(res_polygon, wrk_polygon, op, int_points) | ||
@@ -867,0 +536,0 @@ { |
@@ -602,2 +602,1 @@ /** | ||
} | ||
@@ -5,2 +5,3 @@ "use strict"; | ||
import LinkedList from '../data_structures/linked_list'; | ||
import {END_VERTEX, NOT_VERTEX, START_VERTEX} from "../utils/constants"; | ||
@@ -7,0 +8,0 @@ /** |
@@ -12,2 +12,10 @@ /** | ||
import * as Relations from "../algorithms/relation"; | ||
import { | ||
addToIntPoints, filterDuplicatedIntersections, | ||
getSortedArray, getSortedArrayOnLine, initializeInclusionFlags, insertBetweenIntPoints, | ||
splitByIntersections | ||
} from "../data_structures/smart_intersections"; | ||
import {Multiline} from "./multiline"; | ||
import {intersectEdge2Line} from "../algorithms/intersection"; | ||
import {INSIDE} from "../utils/constants"; | ||
@@ -53,16 +61,20 @@ /** | ||
let argsArray = args[0]; | ||
if (args[0] instanceof Array && args[0].every((loop) => {return loop instanceof Array})) { | ||
if (argsArray.every( el => {return el instanceof Array && el.length === 2 && typeof(el[0]) === "number" && typeof(el[1]) === "number"} )) { | ||
if (args[0] instanceof Array && args[0].every((loop) => { | ||
return loop instanceof Array | ||
})) { | ||
if (argsArray.every(el => { | ||
return el instanceof Array && el.length === 2 && typeof (el[0]) === "number" && typeof (el[1]) === "number" | ||
})) { | ||
this.faces.add(new Flatten.Face(this, argsArray)); // one-loop polygon as array of pairs of numbers | ||
} | ||
else { | ||
} else { | ||
for (let loop of argsArray) { // multi-loop polygon | ||
/* Check extra level of nesting for GeoJSON-style multi polygons */ | ||
if (loop instanceof Array && loop[0] instanceof Array && | ||
loop[0].every( el => {return el instanceof Array && el.length === 2 && typeof(el[0]) === "number" && typeof(el[1]) === "number"} )) { | ||
loop[0].every(el => { | ||
return el instanceof Array && el.length === 2 && typeof (el[0]) === "number" && typeof (el[1]) === "number" | ||
})) { | ||
for (let loop1 of loop) { | ||
this.faces.add(new Flatten.Face(this, loop1)); | ||
} | ||
} | ||
else { | ||
} else { | ||
this.faces.add(new Flatten.Face(this, loop)); | ||
@@ -72,4 +84,3 @@ } | ||
} | ||
} | ||
else { | ||
} else { | ||
this.faces.add(new Flatten.Face(this, argsArray)); // one-loop polygon | ||
@@ -177,2 +188,36 @@ } | ||
/** | ||
* Clear all faces and create new faces from edges | ||
*/ | ||
recreateFaces() { | ||
// Remove all faces | ||
this.faces.clear(); | ||
for (let edge of this.edges) { | ||
edge.face = null; | ||
} | ||
// Restore faces | ||
let first, last; | ||
let unassignedEdgeFound = true; | ||
while (unassignedEdgeFound) { | ||
unassignedEdgeFound = false; | ||
for (let edge of this.edges) { | ||
if (edge.face === null) { | ||
first = edge; | ||
unassignedEdgeFound = true; | ||
break; | ||
} | ||
} | ||
if (unassignedEdgeFound) { | ||
let last = first; | ||
do { | ||
last = last.next; | ||
} while (last.next !== first) | ||
let face = this.addFace(first, last); | ||
} | ||
} | ||
} | ||
/** | ||
* Delete chain of edges from the face. | ||
@@ -250,3 +295,3 @@ * @param {Face} face Face to remove chain | ||
for (let edge of multiline) { | ||
if (edge.setInclusion(this) !== Flatten.INSIDE) | ||
if (edge.setInclusion(this) !== INSIDE) | ||
continue; | ||
@@ -261,4 +306,3 @@ | ||
newCutPolygons.push(polygon); | ||
} | ||
else { | ||
} else { | ||
let [cutPoly1, cutPoly2] = polygon.cutFace(cut_edge_start, cut_edge_end); | ||
@@ -326,2 +370,65 @@ newCutPolygons.push(cutPoly1, cutPoly2); | ||
/** | ||
* 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]); | ||
// smart intersections | ||
let intersections = { | ||
int_points1: [], | ||
int_points2: [], | ||
int_points1_sorted: [], | ||
int_points2_sorted: [] | ||
}; | ||
// intersect line 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); | ||
} | ||
} | ||
// sort smart intersections | ||
intersections.int_points1_sorted = getSortedArrayOnLine(multiline.first.shape, intersections.int_points1); | ||
intersections.int_points2_sorted = getSortedArray(intersections.int_points2); | ||
// split by intersection points | ||
splitByIntersections(multiline, intersections.int_points1_sorted); | ||
splitByIntersections(newPoly, intersections.int_points2_sorted); | ||
// filter duplicated intersection points | ||
filterDuplicatedIntersections(intersections); | ||
// initialize inclusion flags for edges incident to intersections | ||
initializeInclusionFlags(intersections.int_points1); | ||
initializeInclusionFlags(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.setInclusion(newPoly) === INSIDE) { | ||
new_edge = new Flatten.Edge(int_point1_curr.edge_before.shape); | ||
insertBetweenIntPoints(intersections.int_points2[int_point1_prev.id], intersections.int_points2[int_point1_curr.id], new_edge); | ||
new_edge = new Flatten.Edge(int_point1_curr.edge_before.shape.reverse()); | ||
insertBetweenIntPoints(intersections.int_points2[int_point1_curr.id], intersections.int_points2[int_point1_prev.id], new_edge); | ||
} | ||
int_point1_prev = int_point1_curr; | ||
} | ||
// Recreate faces | ||
newPoly.recreateFaces(); | ||
return newPoly; | ||
} | ||
/** | ||
* Returns the first founded edge of polygon that contains given point | ||
@@ -349,7 +456,7 @@ * @param {Point} pt | ||
/* Sort polygons by area in descending order */ | ||
polygons.sort( (polygon1, polygon2) => polygon2.area() - polygon1.area() ); | ||
polygons.sort((polygon1, polygon2) => polygon2.area() - polygon1.area()); | ||
/* define orientation of the island by orientation of the first polygon in array */ | ||
let orientation = [...polygons[0].faces][0].orientation(); | ||
/* Create output array from polygons with same orientation as a first polygon (array of islands) */ | ||
let newPolygons = polygons.filter( polygon => [...polygon.faces][0].orientation() === orientation); | ||
let newPolygons = polygons.filter(polygon => [...polygon.faces][0].orientation() === orientation); | ||
for (let polygon of polygons) { | ||
@@ -392,4 +499,3 @@ let face = [...polygon.faces][0]; | ||
return rel === Flatten.INSIDE || rel === Flatten.BOUNDARY; | ||
} | ||
else { | ||
} else { | ||
return Relations.cover(this, shape); | ||
@@ -478,3 +584,3 @@ } | ||
for (let face of this.faces) { | ||
newPolygon.addFace(face.shapes.map( shape => shape.translate(vec))); | ||
newPolygon.addFace(face.shapes.map(shape => shape.translate(vec))); | ||
} | ||
@@ -495,3 +601,3 @@ return newPolygon; | ||
for (let face of this.faces) { | ||
newPolygon.addFace(face.shapes.map( shape => shape.rotate(angle, center))); | ||
newPolygon.addFace(face.shapes.map(shape => shape.rotate(angle, center))); | ||
} | ||
@@ -509,3 +615,3 @@ return newPolygon; | ||
for (let face of this.faces) { | ||
newPolygon.addFace(face.shapes.map( shape => shape.transform(matrix))); | ||
newPolygon.addFace(face.shapes.map(shape => shape.transform(matrix))); | ||
} | ||
@@ -512,0 +618,0 @@ return newPolygon; |
@@ -30,1 +30,6 @@ /** | ||
export const OVERLAP_OPPOSITE = 2; | ||
export const NOT_VERTEX = 0; | ||
export const START_VERTEX = 1; | ||
export const END_VERTEX = 2; | ||
@@ -845,4 +845,26 @@ /** | ||
}); | ||
}); | ||
it('Can cut polygon with holes by line', () => { | ||
const poly = new Polygon([ | ||
[ | ||
[0, 0], | ||
[100, 0], | ||
[100, 100], | ||
[0, 100] | ||
], | ||
[ | ||
[30, 30], | ||
[30, 70], | ||
[70, 70], | ||
[70, 30] | ||
] | ||
]); | ||
const l = line(point(50, 50), vector(0, 1)); | ||
const res_poly = poly.cutWithLine(l); | ||
expect(res_poly.faces.size).to.equal(2); | ||
expect(res_poly.edges.size).to.equal(12); | ||
}); | ||
}); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
5671471
164
36001