-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpolygon-utilities.js
94 lines (80 loc) · 3.93 KB
/
polygon-utilities.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// -------------------------------------------------------------------------
// Utilities for manipulating polygons on a geometric level
// -------------------------------------------------------------------------
const { distanceToPolygon, distanceBetweenPoints } = require('distance-to-polygon')
const polygonsIntersect = require('polygon-overlap')
const pointInsidePolygon = require('point-in-polygon')
const { getPolygonCenter } = require('./utilities')
const hull = require('hull.js')
const _ = require('lodash')
const getMidPoint = function (x1, y1, x2, y2, per) {
return [x1 + (x2 - x1) * per, y1 + (y2 - y1) * per];
}
// Breaks up any long straight lines in peak polygons into smaller lines connected by points
export const breakLongLinesIntoPoints = (polygon) => {
let newPolygon = polygon.slice(0)
for (let p = 0; p < newPolygon.length - 1; p++) {
const pointOne = newPolygon[p]
const pointTwo = newPolygon[p + 1]
const pointDistance = distanceBetweenPoints(pointOne, pointTwo)
if (pointDistance > 20) {
// Break the line up into 10px segments
const range = _.range(10, pointDistance, 10)
const pointsToAdd = []
for (let step = 0; step < range.length; step++) {
const midPoint = getMidPoint(pointOne[0], pointOne[1], pointTwo[0], pointTwo[1], range[step] / pointDistance)
pointsToAdd.push(midPoint)
}
// Slice in the new points
newPolygon = newPolygon.slice(0, p + 1).concat(pointsToAdd).concat(newPolygon.slice(p + 1))
}
}
return newPolygon
}
// Fix overlapping peak polygons using the zipper method
export const fixOverlappingPolygonsUsingZipper = (polygons) => {
const newPolygons = polygons.slice(0)
for (let i = 0; i < newPolygons.length; i++) {
for (let j = i + 1; j < newPolygons.length; j++) {
if (i === j) {
continue
}
const polygonOne = newPolygons[i].slice(0)
const polygonTwo = newPolygons[j].slice(0)
if (polygonsIntersect(polygonOne, polygonTwo)) {
// Find intersecting points between these two polygons
for (let p = 0; p < polygonOne.length; p++) {
const pointOne = polygonOne[p]
// If this particular point is inside the other polygon
if (pointInsidePolygon(pointOne, polygonTwo)) {
// Find the closest point on the border of the other polygon
let closestPointIndex
let closestPointDistance = Infinity
for (let p2 = 0; p2 < polygonTwo.length; p2++) {
const pointTwo = polygonTwo[p2]
const pointDistance = distanceBetweenPoints(pointOne, pointTwo)
if (pointDistance < closestPointDistance) {
closestPointDistance = pointDistance
closestPointIndex = p2
}
}
if (closestPointDistance > 0) {
// Get the halfway point between the two points
const halfwayPoint = [ (pointOne[0] + polygonTwo[closestPointIndex][0]) / 2, (pointOne[1] + polygonTwo[closestPointIndex][1]) / 2 ]
// Add the halfway point to both polygons and remove both the original points
polygonOne.splice(p, 1, halfwayPoint)
polygonTwo.splice(closestPointIndex, 1, halfwayPoint)
}
}
}
}
newPolygons[i] = polygonOne
newPolygons[j] = polygonTwo
}
}
return newPolygons.map((polygon) => {
// Recalculate the polygon boundary
return hull(polygon, 50)
})
// return newPolygons
}