citygml-validate-shell
Advanced tools
Comparing version 0.1.17 to 0.1.18
173
index.js
@@ -8,2 +8,3 @@ // Note: QIE paper states that only LOD1–3 geometries are to be tested, | ||
// TODO: Test against a CityGML dataset containing valid and invalid geometry | ||
// TODO: Support inner polygons | ||
@@ -68,3 +69,14 @@ var _ = require("lodash"); | ||
return function(callback) { | ||
var edges = findEdges(shell); | ||
var polygonPoints = []; | ||
_.each(shell, function(polygonXML) { | ||
var boundaries = citygmlBoundaries(polygonXML); | ||
_.each(boundaries.exterior.concat(boundaries.interior), function(boundary) { | ||
var bPoints = citygmlPoints(boundary); | ||
polygonPoints.push(bPoints); | ||
}); | ||
}); | ||
var edges = findEdges(polygonPoints); | ||
var edgeCounts = countMatchingEdges(edges); | ||
@@ -99,17 +111,19 @@ | ||
return function(callback) { | ||
var edges = findEdges(shell); | ||
var polygonPoints = []; | ||
var edgesByPolygon = findEdgesByPolygon(edges); | ||
var polygonsByVertex = {}; | ||
_.each(shell, function(polygonXML, polygonIndex) { | ||
_.each(shell, function(polygonXML) { | ||
var boundaries = citygmlBoundaries(polygonXML); | ||
var checkRings = boundaries.exterior.concat(boundaries.interior); | ||
var checkRingXML; | ||
var checkRingPoints; | ||
_.each(boundaries.exterior.concat(boundaries.interior), function(boundary) { | ||
var bPoints = citygmlPoints(boundary); | ||
polygonPoints.push(bPoints); | ||
}); | ||
}); | ||
_.each(checkRings, function(checkRingXML, ringIndex) { | ||
checkRingPoints = citygmlPoints(checkRingXML); | ||
var edges = findEdges(polygonPoints); | ||
var edgesByPolygon = findEdgesByPolygon(edges); | ||
var polygonsByVertex = {}; | ||
_.each(polygonPoints, function(checkRingPoints, polygonIndex) { | ||
_.each(checkRingPoints, function(point) { | ||
@@ -128,3 +142,3 @@ var pointId = point.toString(); | ||
}); | ||
}); | ||
// }); | ||
@@ -203,3 +217,14 @@ var badVertices = []; | ||
return function(callback) { | ||
var edges = findEdges(shell); | ||
var polygonPoints = []; | ||
_.each(shell, function(polygonXML) { | ||
var boundaries = citygmlBoundaries(polygonXML); | ||
_.each(boundaries.exterior.concat(boundaries.interior), function(boundary) { | ||
var bPoints = citygmlPoints(boundary); | ||
polygonPoints.push(bPoints); | ||
}); | ||
}); | ||
var edges = findEdges(polygonPoints); | ||
var edgeCounts = countMatchingEdges(edges); | ||
@@ -231,4 +256,15 @@ | ||
return function(callback) { | ||
var edges = findEdges(shell); | ||
var polygonPoints = []; | ||
_.each(shell, function(polygonXML) { | ||
var boundaries = citygmlBoundaries(polygonXML); | ||
_.each(boundaries.exterior.concat(boundaries.interior), function(boundary) { | ||
var bPoints = citygmlPoints(boundary); | ||
polygonPoints.push(bPoints); | ||
}); | ||
}); | ||
var edges = findEdges(polygonPoints); | ||
// List of edges as strings: [["0,0,0", "0,1,0"], [...]] | ||
@@ -275,10 +311,22 @@ var edgeList = _.map(edges, function(edge) { | ||
return function(callback) { | ||
var checkPolygons = _.clone(shell); | ||
var edges = findEdges(shell); | ||
var polygonPoints = []; | ||
_.each(shell, function(polygonXML) { | ||
var boundaries = citygmlBoundaries(polygonXML); | ||
_.each(boundaries.exterior.concat(boundaries.interior), function(boundary) { | ||
var bPoints = citygmlPoints(boundary); | ||
polygonPoints.push(bPoints); | ||
}); | ||
}); | ||
// var checkPolygons = _.clone(shell); | ||
// var edges = findEdges(shell); | ||
var edges = findEdges(polygonPoints); | ||
var intersections = []; | ||
_.each(shell, function(polygonXML, polygonIndex) { | ||
var checkBoundaries = citygmlBoundaries(polygonXML); | ||
var checkRingPoints = citygmlPoints(checkBoundaries.exterior[0]); | ||
_.each(polygonPoints, function(checkRingPoints, polygonIndex) { | ||
// var checkBoundaries = citygmlBoundaries(polygonXML); | ||
// var checkRingPoints = citygmlPoints(checkBoundaries.exterior[0]); | ||
@@ -348,9 +396,11 @@ // TODO: Should be abstracted into a Plane module as it's also used in | ||
return function(callback) { | ||
var polygonIndexes = []; | ||
var polygonPoints = []; | ||
var polygonWindings = []; | ||
_.each(shell, function(polygonXML) { | ||
_.each(shell, function(polygonXML, polygonIndex) { | ||
var boundaries = citygmlBoundaries(polygonXML); | ||
var exteriorPoints = citygmlPoints(boundaries.exterior[0]); | ||
polygonIndexes.push(polygonIndex); | ||
polygonPoints.push(exteriorPoints); | ||
@@ -404,2 +454,5 @@ }); | ||
var flipped = []; | ||
var outerFlipped = false; | ||
// Pick outer polygon with the largest absolute Z normal as this will always // be on top after the previous filters in a valid solid (has the shallowest | ||
@@ -414,3 +467,3 @@ // angle) and will filter out overhanging polygons | ||
outerPolygon = oPolygon; | ||
outerPolygonIndex = oPolygonIndex; | ||
outerPolygonIndex = Number(oPolygonIndex); | ||
outerPolygonNormal = normal; | ||
@@ -448,9 +501,8 @@ } | ||
callback(null, [new Error("GE_S_ALL_POLYGONS_WRONG_ORIENTATION: All the polygons have the wrong orientation"), indexes]); | ||
return; | ||
} else { | ||
// TODO: This needs to return all the other polygons that are flipped | ||
// too, otherwise it only returns the first one but there might be more | ||
callback(null, [new Error("GE_S_POLYGON_WRONG_ORIENTATION: When an exterior polygon is viewed from outside the shell the points must be ordered counterclockwise"), outerPolygonIndex]); | ||
// This will cause only flipped polygons to be valid, as they match up | ||
// with the flipped outer polygon. | ||
outerFlipped = true; | ||
} | ||
return; | ||
} | ||
@@ -465,3 +517,3 @@ | ||
// Find edges | ||
var edges = findEdges(shell); | ||
var edges = findEdges(polygonPoints); | ||
var edgesByPolygon = findEdgesByPolygon(edges); | ||
@@ -476,4 +528,2 @@ var edgeCounts = countMatchingEdges(edges); | ||
var flipped = []; | ||
_.each(edgeCounts, function(count, edgeId) { | ||
@@ -538,2 +588,10 @@ if (count !== 2) { | ||
// If outer polygon is flipped then everything in the flipped array is | ||
// actually valid (as it was compared against a flipped polygon). We can | ||
// diff the flipped array with the original indexes to get the actually | ||
// flipped polygons. | ||
if (outerFlipped) { | ||
flipped = _.difference(polygonIndexes, flipped); | ||
} | ||
callback(null, [new Error("GE_S_POLYGON_WRONG_ORIENTATION: When an exterior polygon is viewed from outside the shell the points must be ordered counterclockwise"), flipped]); | ||
@@ -543,38 +601,43 @@ }; | ||
var findEdges = function(shell) { | ||
var findEdges = function(polygons) { | ||
var edges = {}; | ||
_.each(shell, function(polygonXML, polygonIndex) { | ||
var boundaries = citygmlBoundaries(polygonXML); | ||
// REMOVED: CityGML-specific processing should be done externally | ||
// _.each(shell, function(polygonXML, polygonIndex) { | ||
// var boundaries = citygmlBoundaries(polygonXML); | ||
// | ||
// var checkRings = boundaries.exterior.concat(boundaries.interior); | ||
// var checkRingXML; | ||
// var checkRingPoints; | ||
// var prevPoint; | ||
// | ||
// _.each(checkRings, function(checkRingXML) { | ||
// checkRingPoints = citygmlPoints(checkRingXML); | ||
var checkRings = boundaries.exterior.concat(boundaries.interior); | ||
var checkRingXML; | ||
var checkRingPoints; | ||
_.each(polygons, function(polygon, polygonIndex) { | ||
var prevPoint; | ||
_.each(polygon, function(point) { | ||
if (!prevPoint) { | ||
prevPoint = point; | ||
return; | ||
} | ||
_.each(checkRings, function(checkRingXML) { | ||
checkRingPoints = citygmlPoints(checkRingXML); | ||
// Serialise edge | ||
var edgeId = prevPoint.toString() + ":" + point.toString(); | ||
_.each(checkRingPoints, function(point) { | ||
if (!prevPoint) { | ||
prevPoint = point; | ||
return; | ||
} | ||
// First time create new edge definition, second time only add polygon | ||
// index to edge | ||
if (!edges[edgeId]) { | ||
edges[edgeId] = [prevPoint, point, [polygonIndex]]; | ||
} else { | ||
edges[edgeId][2].push(polygonIndex); | ||
} | ||
// Serialise edge | ||
var edgeId = prevPoint.toString() + ":" + point.toString(); | ||
// First time create new edge definition, second time only add polygon | ||
// index to edge | ||
if (!edges[edgeId]) { | ||
edges[edgeId] = [prevPoint, point, [polygonIndex]]; | ||
} else { | ||
edges[edgeId][2].push(polygonIndex); | ||
} | ||
prevPoint = point; | ||
}); | ||
prevPoint = point; | ||
}); | ||
}); | ||
// }); | ||
// }); | ||
return edges; | ||
@@ -581,0 +644,0 @@ }; |
{ | ||
"name": "citygml-validate-shell", | ||
"version": "0.1.17", | ||
"version": "0.1.18", | ||
"description": "Validate a CityGML shell against the QIE suite", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -8,2 +8,3 @@ # CityGML Validate Shell | ||
```javascript | ||
var _ = require("lodash"); | ||
var citygmlPolygons = require("citygml-polygons"); | ||
@@ -17,8 +18,12 @@ var citygmlValidateShell = require("citygml-validate-shell"); | ||
citygmlValidateShell(polygons, function(err, results) { | ||
if (err) { | ||
console.log("Shell not valid:", err, results); | ||
} else { | ||
console.log("Shell valid"); | ||
} | ||
_.each(results, function(vError) { | ||
// Should always be an error, but check anyway | ||
if (!vError || !vError[0]) { | ||
return; | ||
} | ||
// Output validation error name | ||
console.log(vError[0].message); | ||
}); | ||
}); | ||
``` |
28826
648
28