UNPKG

sharedstreets

Version:

SharedStreets, a 'digital commons' for the street

470 lines (469 loc) 22.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const helpers_1 = require("@turf/helpers"); const length_1 = __importDefault(require("@turf/length")); const fs = __importStar(require("fs")); const glob = __importStar(require("glob")); const path = __importStar(require("path")); const sharedstreetsPbf = __importStar(require("sharedstreets-pbf")); const sharedstreets = __importStar(require("./src/index")); const envelope_1 = __importDefault(require("@turf/envelope")); const turfHelpers = __importStar(require("@turf/helpers")); const index_1 = require("./src/index"); const index_2 = require("./src/index"); const graph_1 = require("./src/graph"); const tiles_1 = require("./src/tiles"); const geom_1 = require("./src/geom"); const test = require('tape'); const pt1 = [110, 45]; const pt2 = [-74.003388, 40.634538]; const pt3 = [-74.004107, 40.63406]; const BUILD_TEST_OUPUT = false; test("sharedstreets -- test osrm install", (t) => { const osrmPath = require.resolve('osrm'); t.comment('osrmPath: ' + osrmPath); const osrmLibPath = path.dirname(osrmPath); const osrmBinPath = path.join(osrmLibPath, '..'); t.comment('osrmBinPath: ' + osrmBinPath); if (fs.existsSync(osrmBinPath)) { t.comment('osrmBinPath found'); } else t.comment('osrmBinPath not found'); t.end(); }); // core library tests test("sharedstreets -- intersection", (t) => { t.equal(sharedstreets.intersectionId(pt1), "afd3db07d9baa6deef7acfcaac240607", "intersectionId => pt1"); t.equal(sharedstreets.intersectionId(pt2), "f22b51a95400e250bff8d889a738c0b0", "intersectionId => pt2"); t.equal(sharedstreets.intersectionId(pt3), "eed5479e5315e5a2e71760cc70a4ac76", "intersectionId => pt3"); t.equal(sharedstreets.intersectionMessage(pt1), "Intersection 110.00000 45.00000", "intersectionMessage => pt1"); t.equal(sharedstreets.intersectionMessage(pt2), "Intersection -74.00339 40.63454", "intersectionMessage => pt2"); t.equal(sharedstreets.intersectionMessage(pt3), "Intersection -74.00411 40.63406", "intersectionMessage => pt3"); // Extras t.equal(sharedstreets.intersectionId([-74.00962750000001, 40.740100500000004]), "68ea64a9f5be2b3a219898387b3da3e8", "intersectionId => extra1"); t.equal(sharedstreets.intersectionMessage([-74.00962750000001, 40.740100500000004]), "Intersection -74.00963 40.74010", "intersectionMessage => extra1"); t.end(); }); test("sharedstreets -- referenceId", (t) => { const locationReferenceOutbound = sharedstreets.locationReference([-74.0048213, 40.7416415], { outboundBearing: 208, distanceToNextRef: 9279 }); const locationReferenceInbound = sharedstreets.locationReference([-74.0051265, 40.7408505], { inboundBearing: 188 }); const formOfWay = 2; // => "MultipleCarriageway" t.equal(locationReferenceOutbound.intersectionId, "6d9fe428bc29b591ca1830d44e73099d", "locationReferenceOutbound => intersectionId"); t.equal(locationReferenceInbound.intersectionId, "5a44762edbad541f0fb808c44c018105", "locationReferenceInbound => intersectionId"); var refHash = sharedstreets.generateHash("Reference 2 -74.00482 40.74164 208 93 -74.00513 40.74085"); t.equal(sharedstreets.referenceMessage([locationReferenceOutbound, locationReferenceInbound], formOfWay), "Reference 2 -74.00482 40.74164 208 93 -74.00513 40.74085", "referenceId => pt1"); t.equal(sharedstreets.referenceId([locationReferenceOutbound, locationReferenceInbound], formOfWay), refHash, "referenceId => pt1"); t.end(); }); test("sharedstreets -- locationReference", (t) => { const options = { distanceToNextRef: 9279, outboundBearing: 208, }; const locRef = sharedstreets.locationReference([-74.0048213, 40.7416415], options); var intersectionHash = sharedstreets.generateHash("Intersection -74.00482 40.74164"); t.equal(locRef.intersectionId, intersectionHash, "locRef => intersectionId"); t.end(); }); test("sharedstreets-pbf -- intersection", (t) => { var count = 1; for (var filepath of glob.sync(path.join('./', "test", "pbf", `*.intersection.6.pbf`))) { const buffer = fs.readFileSync(filepath); const intersections = sharedstreetsPbf.intersection(buffer); for (var intersection of intersections) { count++; if (count > 10) break; const { lon, lat, id, nodeId } = intersection; const expectedId = sharedstreets.intersectionId([lon, lat], nodeId); const message = sharedstreets.intersectionMessage([lon, lat], nodeId); t.equal(expectedId, id, `[${message}] => ${id}`); } } t.end(); }); test("sharedstreets-pbf -- geometry", (t) => { var count = 1; for (var filepath of glob.sync(path.join('./', "test", "pbf", `*.geometry.6.pbf`))) { const buffer = fs.readFileSync(filepath); const geometries = sharedstreetsPbf.geometry(buffer); for (var geometry of geometries) { count++; if (count > 10) break; const { lonlats, id } = geometry; const coords = sharedstreets.lonlatsToCoords(lonlats); const expectedId = sharedstreets.geometryId(coords); const message = sharedstreets.geometryMessage(coords); t.equal(expectedId, id, `[${message}] => ${id}`); } } t.end(); }); test("sharedstreets-pbf -- reference", (t) => { var count = 1; for (var filepath of glob.sync(path.join('./', "test", "pbf", `*.reference.6.pbf`))) { const buffer = fs.readFileSync(filepath); const references = sharedstreetsPbf.reference(buffer); for (var reference of references) { count++; if (count > 10) break; const { locationReferences, id, formOfWay } = reference; const expectedId = sharedstreets.referenceId(locationReferences, formOfWay); const message = sharedstreets.referenceMessage(locationReferences, formOfWay); t.equal(expectedId, id, `["${message}": ${expectedId}] => ${id}`); } } t.end(); }); test("sharedstreets -- coordsToLonlats", (t) => { const lonlats = sharedstreets.coordsToLonlats([[110, 45], [120, 55]]); t.deepEqual(lonlats, [110, 45, 120, 55]); t.end(); }); test("sharedstreets -- geometry", (t) => { const line = helpers_1.lineString([[110, 45], [115, 50], [120, 55]]); const geom = sharedstreets.geometry(line); var geomHash = sharedstreets.generateHash("Geometry 110.00000 45.00000 115.00000 50.00000 120.00000 55.00000"); t.equal(geom.id, geomHash); t.end(); }); test("sharedstreets -- intersection", (t) => { const intersect = sharedstreets.intersection([110, 45]); t.deepEqual(intersect, { id: "afd3db07d9baa6deef7acfcaac240607", lat: 45, lon: 110, inboundReferenceIds: [], outboundReferenceIds: [], }); t.end(); }); test("sharedstreets -- reference", (t) => { const line = helpers_1.lineString([[110, 45], [115, 50], [120, 55]]); const geom = sharedstreets.geometry(line); const locationReferences = [ sharedstreets.locationReference([-74.0048213, 40.7416415], { outboundBearing: 208, distanceToNextRef: 9279 }), sharedstreets.locationReference([-74.0051265, 40.7408505], { inboundBearing: 188 }), ]; const formOfWay = 0; // => "Other" const ref = sharedstreets.reference(geom, locationReferences, formOfWay); const refHash = sharedstreets.generateHash("Reference 0 -74.00482 40.74164 208 93 -74.00513 40.74085"); t.equal(ref.id, refHash); t.end(); }); test("sharedstreets -- metadata", (t) => { const line = helpers_1.lineString([[110, 45], [115, 50], [120, 55]]); const gisMetadata = [{ source: "sharedstreets", sections: [{ sectionId: "foo", sectionProperties: "bar" }] }]; const geom = sharedstreets.geometry(line); const metadata = sharedstreets.metadata(geom, {}, gisMetadata); t.deepEqual(metadata, { geometryId: "723cda09fa38e07e0957ae939eb2684f", osmMetadata: {}, gisMetadata: [ { source: "sharedstreets", sections: [{ sectionId: "foo", sectionProperties: "bar" }] }, ], }); t.end(); }); test("sharedstreets -- getFormOfWay", (t) => { const lineA = helpers_1.lineString([[110, 45], [115, 50], [120, 55]], { formOfWay: 3 }); const lineB = helpers_1.lineString([[110, 45], [115, 50], [120, 55]]); const lineC = helpers_1.lineString([[110, 45], [115, 50], [120, 55]], { formOfWay: "Motorway" }); t.equal(sharedstreets.getFormOfWay(lineA), 3); t.equal(sharedstreets.getFormOfWay(lineB), 0); t.equal(sharedstreets.getFormOfWay(lineC), 1); t.end(); }); test("sharedstreets -- forwardReference", (t) => { const line = helpers_1.lineString([[110, 45], [115, 50], [120, 55]]); const forwardReference = sharedstreets.forwardReference(line).id; const backReference = sharedstreets.backReference(line).id; t.equal(forwardReference, "035dc67e1230f1f6c6ec63997f86ba27"); t.equal(backReference, "21993e8f0cdb8fa629418b78552a4503"); t.end(); }); test("sharedstreets -- bearing & distance", (t) => { const line = helpers_1.lineString([[-74.006449, 40.739405000000005], [-74.00790070000001, 40.7393884], [-74.00805100000001, 40.7393804]]); const lineLength = length_1.default(line); const inboundBearing = sharedstreets.inboundBearing(line, lineLength, lineLength); const outboundBearing = sharedstreets.outboundBearing(line, lineLength, 0); const distanceToNextRef = sharedstreets.distanceToNextRef(line); t.equal(outboundBearing, 269); // => 269 Java Implementation t.equal(inboundBearing, 269); // => 267 Java Implementation t.equal(distanceToNextRef, 13502); // => 13502 Java Implementation t.end(); }); test("sharedstreets -- round", (t) => { t.equal(Number(sharedstreets.round(10.123456789)), 10.12346); t.end(); }); test("sharedstreets -- closed loops - Issue #8", (t) => { // https://github.com/sharedstreets/sharedstreets-conflator/issues/8 const line = helpers_1.lineString([ [-79.549159053, 43.615639543], [-79.548687537, 43.615687142], [-79.547733353, 43.615744613], [-79.548036429, 43.614913292], [-79.549024608, 43.615542992], [-79.549159053, 43.615639543], ]); t.assert(sharedstreets.forwardReference(line)); t.assert(sharedstreets.backReference(line)); t.end(); }); // cache module tests test("tiles -- generate tile ids ", (t) => { // test polygon (dc area) var poloygon = { "type": "Feature", "properties": {}, "geometry": { "type": "Polygon", "coordinates": [ [[-77.0511531829834, 38.88588861057251], [-77.00746536254883, 38.88588861057251], [-77.00746536254883, 38.91407701203291], [-77.0511531829834, 38.91407701203291], [-77.0511531829834, 38.88588861057251]] ] } }; // test tiles for polygon var tiles1 = tiles_1.getTileIdsForPolygon(poloygon); t.deepEqual(tiles1, ["12-1171-1566", "12-1171-1567"]); // test buffering var tiles2 = tiles_1.getTileIdsForPolygon(poloygon, 10000); t.deepEqual(tiles2, ["12-1170-1566", "12-1170-1567", "12-1171-1566", "12-1171-1567", "12-1172-1566", "12-1172-1567"]); // test polygon (dc area) var point = turfHelpers.point([-77.0511531829834, 38.88588861057251]); // test tiles for point var tiles3 = tiles_1.getTileIdsForPoint(point, 10); t.deepEqual(tiles3, ["12-1171-1567"]); // test buffering var tiles4 = tiles_1.getTileIdsForPoint(point, 10000); t.deepEqual(tiles4, ["12-1170-1566", "12-1170-1567", "12-1170-1568", "12-1171-1566", "12-1171-1567", "12-1171-1568", "12-1172-1566", "12-1172-1567", "12-1172-1568"]); t.end(); }); test("tiles -- build tile paths ", (t) => { var pathString = 'osm/planet-180430/12-1171-1566.geometry.6.pbf'; // test path parsing var tilePath = new index_2.TilePath(pathString); t.deepEqual(tilePath, { "tileId": "12-1171-1566", "tileType": "geometry", "source": "osm/planet-180430", "tileHierarchy": 6 }); // test path string builder var pathString2 = tilePath.toPathString(); t.equal(pathString, pathString2); // test path group var pathGroup = new index_2.TilePathGroup([tilePath]); t.deepEqual(pathGroup, { source: 'osm/planet-180430', tileHierarchy: 6, tileTypes: ['geometry'], tileIds: ['12-1171-1566'] }); // test path gruop eumeration t.deepEqual([...pathGroup], [{ source: 'osm/planet-180430', tileHierarchy: 6, tileType: 'geometry', tileId: '12-1171-1566' }]); t.end(); }); test("tiles -- fetch/parse protobuf filese", (t) => __awaiter(void 0, void 0, void 0, function* () { // get data var tilePath = new index_2.TilePath('osm/planet-180430/12-1171-1566.geometry.6.pbf'); var data = yield tiles_1.getTile(tilePath); t.equal(data.length, 7352); t.end(); })); test("cache -- load data", (t) => __awaiter(void 0, void 0, void 0, function* () { // test polygon (dc area) var polygon = { "type": "Feature", "properties": {}, "geometry": { "type": "Polygon", "coordinates": [ [[-77.0511531829834, 38.88588861057251], [-77.00746536254883, 38.88588861057251], [-77.00746536254883, 38.91407701203291], [-77.0511531829834, 38.91407701203291], [-77.0511531829834, 38.88588861057251]] ] } }; var tilesIds = tiles_1.getTileIdsForPolygon(polygon); var params = new index_2.TilePathParams(); params.source = 'osm/planet-180430'; params.tileHierarchy = 6; var tilePathGroup = index_2.TilePathGroup.fromPolygon(polygon, 0, params); tilePathGroup.addType(index_2.TileType.GEOMETRY); var tileIndex = new index_1.TileIndex(); yield tileIndex.indexTilesByPathGroup(tilePathGroup); t.equal(tileIndex.tiles.size, 2); tilePathGroup.addType(index_2.TileType.INTERSECTION); yield tileIndex.indexTilesByPathGroup(tilePathGroup); t.equal(tileIndex.tiles.size, 4); var data = yield tileIndex.intersects(polygon, index_2.TileType.GEOMETRY, 0, params); t.equal(data.features.length, 2102); var data = yield tileIndex.intersects(polygon, index_2.TileType.INTERSECTION, 0, params); t.equal(data.features.length, 1162); t.end(); })); test("tileIndex -- point data", (t) => __awaiter(void 0, void 0, void 0, function* () { // test polygon (dc area) const content = fs.readFileSync('test/geojson/points_1.in.geojson'); var points = JSON.parse(content.toLocaleString()); var params = new index_2.TilePathParams(); params.source = 'osm/planet-180430'; params.tileHierarchy = 6; // test nearby var tileIndex = new index_1.TileIndex(); var featureCount = 0; for (var point of points.features) { var foundFeatures = yield tileIndex.nearby(point, index_2.TileType.GEOMETRY, 10, params); featureCount += foundFeatures.features.length; } t.equal(featureCount, 3); t.end(); })); test("match points", (t) => __awaiter(void 0, void 0, void 0, function* () { // test polygon (dc area) const content = fs.readFileSync('test/geojson/points_1.in.geojson'); var pointsIn = JSON.parse(content.toLocaleString()); var cleanedPoints = new geom_1.CleanedPoints(pointsIn); var points = turfHelpers.featureCollection(cleanedPoints.clean); var params = new index_2.TilePathParams(); params.source = 'osm/planet-180430'; params.tileHierarchy = 6; // test matcher point candidates var matcher = new graph_1.Graph(null, params); var matchedPoints = []; for (let searchPoint of points.features) { let matches = yield matcher.matchPoint(searchPoint, null, 3); for (let match of matches) { matchedPoints.push(match.toFeature()); } } const matchedPointFeatureCollection_1a = turfHelpers.featureCollection(matchedPoints); const expected_1a_file = 'test/geojson/points_1a.out.geojson'; if (BUILD_TEST_OUPUT) { var expected_1a_out = JSON.stringify(matchedPointFeatureCollection_1a); fs.writeFileSync(expected_1a_file, expected_1a_out); } const expected_1a_in = fs.readFileSync(expected_1a_file); const expected_1a = JSON.parse(expected_1a_in.toLocaleString()); t.deepEqual(expected_1a, matchedPointFeatureCollection_1a); matcher.searchRadius = 1000; var matchedPoints = []; let matches = yield matcher.matchPoint(points.features[0], null, 10); for (let match of matches) { matchedPoints.push(match.toFeature()); } const matchedPointFeatureCollection_1b = turfHelpers.featureCollection(matchedPoints); const expected_1b_file = 'test/geojson/points_1b.out.geojson'; if (BUILD_TEST_OUPUT) { var expected_1b_out = JSON.stringify(matchedPointFeatureCollection_1b); fs.writeFileSync(expected_1b_file, expected_1b_out); } const expected_1b_in = fs.readFileSync(expected_1b_file); const expected_1b = JSON.parse(expected_1b_in.toLocaleString()); t.deepEqual(expected_1b, matchedPointFeatureCollection_1b); t.end(); })); test("match lines 1", (t) => __awaiter(void 0, void 0, void 0, function* () { // test polygon (dc area) const content = fs.readFileSync('test/geojson/sf_centerlines.sample.geojson'); var linesIn = JSON.parse(content.toLocaleString()); var cleanedLines = new geom_1.CleanedLines(linesIn); var lines = turfHelpers.featureCollection(cleanedLines.clean); var params = new index_2.TilePathParams(); params.source = 'osm/planet-180430'; params.tileHierarchy = 6; //test matcher point candidates var matcher = new graph_1.Graph(envelope_1.default(lines), params); yield matcher.buildGraph(); var matchedLines = turfHelpers.featureCollection([]); for (var line of lines.features) { var pathCandidate = yield matcher.matchGeom(line); matchedLines.features.push(pathCandidate.matchedPath); } const expected_1a_file = 'test/geojson/sf_centerlines.sample.out.geojson'; if (BUILD_TEST_OUPUT) { var expected_1a_out = JSON.stringify(matchedLines); fs.writeFileSync(expected_1a_file, expected_1a_out); } const expected_1a_in = fs.readFileSync(expected_1a_file); const expected_1a = JSON.parse(expected_1a_in.toLocaleString()); t.deepEqual(matchedLines, expected_1a); t.end(); })); test("match lines 2 -- snapping and directed edges", (t) => __awaiter(void 0, void 0, void 0, function* () { // test polygon (dc area) const content = fs.readFileSync('test/geojson/line-directed-test.in.geojson'); var linesIn = JSON.parse(content.toLocaleString()); var cleanedLines = new geom_1.CleanedLines(linesIn); var lines = turfHelpers.featureCollection(cleanedLines.clean); var params = new index_2.TilePathParams(); params.source = 'osm/planet-180430'; params.tileHierarchy = 6; //test matcher point candidates var matcher = new graph_1.Graph(envelope_1.default(lines), params); yield matcher.buildGraph(); matcher.searchRadius = 20; matcher.snapIntersections = true; var matchedLines = turfHelpers.featureCollection([]); for (var line of lines.features) { var pathCandidate = yield matcher.matchGeom(line); if (pathCandidate) matchedLines.features.push(pathCandidate.matchedPath); } const expected_1a_file = 'test/geojson/line-directed-test-snapped.out.geojson'; if (BUILD_TEST_OUPUT) { var expected_1a_out = JSON.stringify(matchedLines); fs.writeFileSync(expected_1a_file, expected_1a_out); } const expected_1a_in = fs.readFileSync(expected_1a_file); const expected_1a = JSON.parse(expected_1a_in.toLocaleString()); t.deepEqual(matchedLines, expected_1a); matcher.snapIntersections = false; var matchedLines = turfHelpers.featureCollection([]); for (var line of lines.features) { var pathCandidate = yield matcher.matchGeom(line); if (pathCandidate) matchedLines.features.push(pathCandidate.matchedPath); } const expected_1b_file = 'test/geojson/line-directed-test-unsnapped.out.geojson'; if (BUILD_TEST_OUPUT) { var expected_1b_out = JSON.stringify(matchedLines); fs.writeFileSync(expected_1b_file, expected_1b_out); } const expected_1b_in = fs.readFileSync(expected_1b_file); const expected_1b = JSON.parse(expected_1b_in.toLocaleString()); t.deepEqual(matchedLines, expected_1b); t.end(); }));