Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

clean-pslg

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

clean-pslg - npm Package Compare versions

Comparing version 1.1.0 to 1.1.1

test/crash.js

283

clean-pslg.js

@@ -7,3 +7,2 @@ 'use strict'

var boxIntersect = require('box-intersect')
var compareCell = require('compare-cell')
var segseg = require('robust-segment-intersect')

@@ -18,19 +17,15 @@ var rat = require('big-rat')

//Bounds on a rational number when rounded to a float
function boundRat(r) {
// Bounds on a rational number when rounded to a float
function boundRat (r) {
var f = ratToFloat(r)
var cmp = ratCmp(rat(f), r)
if(cmp < 0) {
return [f, nextafter(f, Infinity)]
} else if(cmp > 0) {
return [nextafter(f, -Infinity), f]
} else {
return [f, f]
}
return [
nextafter(f, -Infinity),
nextafter(f, Infinity)
]
}
//Convert a list of edges in a pslg to bounding boxes
function boundEdges(points, edges) {
// Convert a list of edges in a pslg to bounding boxes
function boundEdges (points, edges) {
var bounds = new Array(edges.length)
for(var i=0; i<edges.length; ++i) {
for (var i = 0; i < edges.length; ++i) {
var e = edges[i]

@@ -40,6 +35,7 @@ var a = points[e[0]]

bounds[i] = [
Math.min(a[0], b[0]),
Math.min(a[1], b[1]),
Math.max(a[0], b[0]),
Math.max(a[1], b[1]) ]
nextafter(Math.min(a[0], b[0]), -Infinity),
nextafter(Math.min(a[1], b[1]), -Infinity),
nextafter(Math.max(a[0], b[0]), Infinity),
nextafter(Math.max(a[1], b[1]), Infinity)
]
}

@@ -49,8 +45,13 @@ return bounds

//Convert a list of points into bounding boxes by duplicating coords
function boundPoints(points) {
// Convert a list of points into bounding boxes by duplicating coords
function boundPoints (points) {
var bounds = new Array(points.length)
for(var i=0; i<points.length; ++i) {
for (var i = 0; i < points.length; ++i) {
var p = points[i]
bounds[i] = [ p[0], p[1], p[0], p[1] ]
bounds[i] = [
nextafter(p[0], -Infinity),
nextafter(p[1], -Infinity),
nextafter(p[0], Infinity),
nextafter(p[1], Infinity)
]
}

@@ -60,11 +61,11 @@ return bounds

//Find all pairs of crossing edges in a pslg (given edge bounds)
function getCrossings(points, edges, edgeBounds) {
// Find all pairs of crossing edges in a pslg (given edge bounds)
function getCrossings (points, edges, edgeBounds) {
var result = []
boxIntersect(edgeBounds, function(i, j) {
boxIntersect(edgeBounds, function (i, j) {
var e = edges[i]
var f = edges[j]
if(e[0] === f[0] || e[0] === f[1] ||
e[1] === f[0] || e[1] === f[1]) {
return
if (e[0] === f[0] || e[0] === f[1] ||
e[1] === f[0] || e[1] === f[1]) {
return
}

@@ -75,3 +76,3 @@ var a = points[e[0]]

var d = points[f[1]]
if(segseg(a, b, c, d)) {
if (segseg(a, b, c, d)) {
result.push([i, j])

@@ -83,8 +84,8 @@ }

//Find all pairs of crossing vertices in a pslg (given edge/vert bounds)
function getTJunctions(points, edges, edgeBounds, vertBounds) {
// Find all pairs of crossing vertices in a pslg (given edge/vert bounds)
function getTJunctions (points, edges, edgeBounds, vertBounds) {
var result = []
boxIntersect(edgeBounds, vertBounds, function(i, v) {
boxIntersect(edgeBounds, vertBounds, function (i, v) {
var e = edges[i]
if(e[0] === v || e[1] === v) {
if (e[0] === v || e[1] === v) {
return

@@ -95,3 +96,3 @@ }

var b = points[e[1]]
if(segseg(a, b, p, p)) {
if (segseg(a, b, p, p)) {
result.push([i, v])

@@ -103,11 +104,14 @@ }

// Cut edges along crossings/tjunctions
function cutEdges (floatPoints, edges, crossings, junctions, useColor) {
var i, e
//Cut edges along crossings/tjunctions
function cutEdges(floatPoints, edges, crossings, junctions, useColor) {
//Convert crossings into tjunctions by constructing rational points
var ratPoints = []
for(var i=0; i<crossings.length; ++i) {
// Convert crossings into tjunctions by constructing rational points
var ratPoints = floatPoints.map((p) => [
rat(p[0]),
rat(p[1])
])
for (i = 0; i < crossings.length; ++i) {
var crossing = crossings[i]
var e = crossing[0]
e = crossing[0]
var f = crossing[1]

@@ -121,7 +125,8 @@ var ee = edges[e]

ratVec(floatPoints[ef[1]]))
if(!x) {
//Segments are parallel, should already be handled by t-junctions
if (!x) {
// Segments are parallel, should already be handled by t-junctions
continue
}
var idx = ratPoints.length + floatPoints.length
var idx = floatPoints.length
floatPoints.push([ratToFloat(x[0]), ratToFloat(x[1])])
ratPoints.push(x)

@@ -131,23 +136,16 @@ junctions.push([e, idx], [f, idx])

//Sort tjunctions
function getPoint(idx) {
if(idx >= floatPoints.length) {
return ratPoints[idx-floatPoints.length]
}
var p = floatPoints[idx]
return [ rat(p[0]), rat(p[1]) ]
}
junctions.sort(function(a, b) {
if(a[0] !== b[0]) {
// Sort tjunctions
junctions.sort(function (a, b) {
if (a[0] !== b[0]) {
return a[0] - b[0]
}
var u = getPoint(a[1])
var v = getPoint(b[1])
var u = ratPoints[a[1]]
var v = ratPoints[b[1]]
return ratCmp(u[0], v[0]) || ratCmp(u[1], v[1])
})
//Split edges along junctions
for(var i=junctions.length-1; i>=0; --i) {
// Split edges along junctions
for (i = junctions.length - 1; i >= 0; --i) {
var junction = junctions[i]
var e = junction[0]
e = junction[0]

@@ -158,6 +156,6 @@ var edge = edges[e]

//Check if edge is not lexicographically sorted
// Check if edge is not lexicographically sorted
var a = floatPoints[s]
var b = floatPoints[t]
if(((a[0] - b[0]) || (a[1] - b[1])) < 0) {
if (((a[0] - b[0]) || (a[1] - b[1])) < 0) {
var tmp = s

@@ -168,17 +166,17 @@ s = t

//Split leading edge
// Split leading edge
edge[0] = s
var last = edge[1] = junction[1]
//If we are grouping edges by color, remember to track data
// If we are grouping edges by color, remember to track data
var color
if(useColor) {
if (useColor) {
color = edge[2]
}
//Split other edges
while(i > 0 && junctions[i-1][0] === e) {
// Split other edges
while (i > 0 && junctions[i - 1][0] === e) {
var junction = junctions[--i]
var next = junction[1]
if(useColor) {
if (useColor) {
edges.push([last, next, color])

@@ -191,4 +189,4 @@ } else {

//Add final edge
if(useColor) {
// Add final edge
if (useColor) {
edges.push([last, t, color])

@@ -200,52 +198,67 @@ } else {

//Return constructed rational points
// Return constructed rational points
return ratPoints
}
//Merge overlapping points
function dedupPoints(floatPoints, ratPoints, floatBounds) {
var numPoints = floatPoints.length + ratPoints.length
var uf = new UnionFind(numPoints)
// Merge overlapping points
function dedupPoints (floatPoints, ratPoints, floatBounds) {
var numPoints = ratPoints.length
var uf = new UnionFind(numPoints)
//Compute rational bounds
var bounds = floatBounds
for(var i=0; i<ratPoints.length; ++i) {
// Compute rational bounds
var bounds = []
for (var i = 0; i < ratPoints.length; ++i) {
var p = ratPoints[i]
var xb = boundRat(p[0])
var yb = boundRat(p[1])
bounds.push([ xb[0], yb[0], xb[1], yb[1] ])
floatPoints.push([ ratToFloat(p[0]), ratToFloat(p[1]) ])
bounds.push([
nextafter(xb[0], -Infinity),
nextafter(yb[0], -Infinity),
nextafter(xb[1], Infinity),
nextafter(yb[1], Infinity)
])
}
//Link all points with over lapping boxes
boxIntersect(bounds, function(i, j) {
// Link all points with over lapping boxes
boxIntersect(bounds, function (i, j) {
uf.link(i, j)
})
//Call find on each point to get a relabeling
var ptr = 0
// Do 1 pass over points to combine points in label sets
var noDupes = true
var labels = new Array(numPoints)
for(var i=0; i<numPoints; ++i) {
for (var i = 0; i < numPoints; ++i) {
var j = uf.find(i)
if(j === i) {
//If not a duplicate, then don't bother
if (j !== i) {
// Clear no-dupes flag, zero out label
noDupes = false
// Make each point the top-left point from its cell
floatPoints[j] = [
Math.min(floatPoints[i][0], floatPoints[j][0]),
Math.min(floatPoints[i][1], floatPoints[j][1])
]
}
}
// If no duplicates, return null to signal termination
if (noDupes) {
return null
}
var ptr = 0
for (var i = 0; i < numPoints; ++i) {
var j = uf.find(i)
if (j === i) {
labels[i] = ptr
floatPoints[ptr++] = floatPoints[i]
} else {
//Clear no-dupes flag, zero out label
noDupes = false
labels[i] = -1
}
}
floatPoints.length = ptr
//If no duplicates, return null to signal termination
if(noDupes) {
return null
}
//Do a second pass to fix up missing labels
for(var i=0; i<numPoints; ++i) {
if(labels[i] < 0) {
// Do a second pass to fix up missing labels
for (var i = 0; i < numPoints; ++i) {
if (labels[i] < 0) {
labels[i] = labels[uf.find(i)]

@@ -255,15 +268,15 @@ }

//Return resulting union-find data structure
// Return resulting union-find data structure
return labels
}
function compareLex2(a,b) { return (a[0]-b[0]) || (a[1]-b[1]) }
function compareLex3(a,b) {
function compareLex2 (a, b) { return (a[0] - b[0]) || (a[1] - b[1]) }
function compareLex3 (a, b) {
var d = (a[0] - b[0]) || (a[1] - b[1])
if(d) {
if (d) {
return d
}
if(a[2] < b[2]) {
if (a[2] < b[2]) {
return -1
} else if(a[2] > b[2]) {
} else if (a[2] > b[2]) {
return 1

@@ -274,9 +287,9 @@ }

//Remove duplicate edge labels
function dedupEdges(edges, labels, useColor) {
if(edges.length === 0) {
// Remove duplicate edge labels
function dedupEdges (edges, labels, useColor) {
if (edges.length === 0) {
return
}
if(labels) {
for(var i=0; i<edges.length; ++i) {
if (labels) {
for (var i = 0; i < edges.length; ++i) {
var e = edges[i]

@@ -289,3 +302,3 @@ var a = labels[e[0]]

} else {
for(var i=0; i<edges.length; ++i) {
for (var i = 0; i < edges.length; ++i) {
var e = edges[i]

@@ -298,3 +311,3 @@ var a = e[0]

}
if(useColor) {
if (useColor) {
edges.sort(compareLex3)

@@ -305,6 +318,6 @@ } else {

var ptr = 1
for(var i=1; i<edges.length; ++i) {
var prev = edges[i-1]
for (var i = 1; i < edges.length; ++i) {
var prev = edges[i - 1]
var next = edges[i]
if(next[0] === prev[0] && next[1] === prev[1] &&
if (next[0] === prev[0] && next[1] === prev[1] &&
(!useColor || next[2] === prev[2])) {

@@ -318,8 +331,13 @@ continue

//Repeat until convergence
function snapRound(points, edges, useColor) {
function preRound (points, edges, useColor) {
var labels = dedupPoints(points, [], boundPoints(points))
dedupEdges(edges, labels, useColor)
return !!labels
}
// Repeat until convergence
function snapRound (points, edges, useColor) {
// 1. find edge crossings
var edgeBounds = boundEdges(points, edges)
var crossings = getCrossings(points, edges, edgeBounds)
var crossings = getCrossings(points, edges, edgeBounds)

@@ -331,12 +349,12 @@ // 2. find t-junctions

// 3. cut edges, construct rational points
var ratPoints = cutEdges(points, edges, crossings, tjunctions, useColor)
var ratPoints = cutEdges(points, edges, crossings, tjunctions, useColor)
// 4. dedupe verts
var labels = dedupPoints(points, ratPoints, vertBounds)
var labels = dedupPoints(points, ratPoints, vertBounds)
// 6. dedupe edges
// 5. dedupe edges
dedupEdges(edges, labels, useColor)
// 5. check termination
if(!labels) {
// 6. check termination
if (!labels) {
return (crossings.length > 0 || tjunctions.length > 0)

@@ -349,12 +367,10 @@ }

//Main loop, runs PSLG clean up until completion
function cleanPSLG(points, edges, colors) {
var modified = false
//If using colors, augment edges with color data
// Main loop, runs PSLG clean up until completion
function cleanPSLG (points, edges, colors) {
// If using colors, augment edges with color data
var prevEdges
if(colors) {
if (colors) {
prevEdges = edges
var augEdges = new Array(edges.length)
for(var i=0; i<edges.length; ++i) {
for (var i = 0; i < edges.length; ++i) {
var e = edges[i]

@@ -366,12 +382,15 @@ augEdges[i] = [e[0], e[1], colors[i]]

//Run snap rounding until convergence
while(snapRound(points, edges, !!colors)) {
// First round: remove duplicate edges and points
var modified = preRound(points, edges, !!colors)
// Run snap rounding until convergence
while (snapRound(points, edges, !!colors)) {
modified = true
}
//Strip color tags
if(!!colors && modified) {
// Strip color tags
if (!!colors && modified) {
prevEdges.length = 0
colors.length = 0
for(var i=0; i<edges.length; ++i) {
for (var i = 0; i < edges.length; ++i) {
var e = edges[i]

@@ -378,0 +397,0 @@ prevEdges.push([e[0], e[1]])

'use strict'
//TODO: Move this to a separate module
module.exports = solveIntersection

@@ -15,9 +13,7 @@

var toFloat = require('big-rat/to-float')
function ratPerp(a, b) {
function ratPerp (a, b) {
return ratSub(ratMul(a[0], b[1]), ratMul(a[1], b[0]))
}
//Solve for intersection
// Solve for intersection
// x = a + t (b-a)

@@ -29,3 +25,3 @@ // (x - c) ^ (d-c) = 0

function solveIntersection(a, b, c, d) {
function solveIntersection (a, b, c, d) {
var ba = rvSub(b, a)

@@ -36,3 +32,3 @@ var dc = rvSub(d, c)

if(ratSign(baXdc) === 0) {
if (ratSign(baXdc) === 0) {
return null

@@ -45,4 +41,6 @@ }

var t = ratDiv(dcXac, baXdc)
var s = rvMuls(ba, t)
var r = rvAdd(a, s)
return rvAdd(a, rvMuls(ba, t))
return r
}
{
"name": "clean-pslg",
"version": "1.1.0",
"version": "1.1.1",
"description": "Remove self intersections, t-junctions and duplicate edges/vertices from a planar straight line graph",

@@ -11,7 +11,6 @@ "main": "clean-pslg.js",

"dependencies": {
"big-rat": "^1.0.1",
"big-rat": "^1.0.3",
"box-intersect": "^1.0.1",
"compare-cell": "^1.0.0",
"nextafter": "^1.0.0",
"rat-vec": "^1.1.0",
"rat-vec": "^1.1.1",
"robust-segment-intersect": "^1.0.1",

@@ -18,0 +17,0 @@ "union-find": "^1.0.2",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc