Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/gm3/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@ import {

import Mark from "markup-js";

import { addProjDef, getMapSourceName, getLayerName, FORMAT_OPTIONS, parseQuery } from "./util";
import {
ensureProjection,
getMapSourceName,
getLayerName,
FORMAT_OPTIONS,
parseQuery,
} from "./util";
import { normalizeFieldValues, normalizeSelection } from "./query/util";

import i18nConfigure from "./i18n";
Expand Down Expand Up @@ -905,7 +911,7 @@ class Application {
* @param {string} projDef.def - a string definition of the projection, in WKT/Proj format
*/
addProjection(projDef) {
addProjDef(proj4, projDef.ref, projDef.def);
ensureProjection(projDef.ref, projDef.def);
}

/* Short hand for toggling the highlight of features.
Expand Down
6 changes: 2 additions & 4 deletions src/gm3/components/coordinate-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import React from "react";
import USNG from "usng-tools-js";
import proj4 from "proj4";

import { addProjDef } from "../util";
import { ensureProjection } from "../util";

import * as proj from "ol/proj";

Expand Down Expand Up @@ -117,9 +117,7 @@ export default class CoordinateDisplay extends React.Component {
if (this.props.projections) {
this.projections = [];
for (const projection of this.props.projections) {
if (typeof projection.projDef !== "undefined") {
addProjDef(proj4, projection.ref, projection.projDef);
}
ensureProjection(projection.ref, projection.projDef);
const isNamedProjection = this.namedProjections.indexOf(projection.ref) !== -1;
let isDefinedProjection = false;
if (!isNamedProjection) {
Expand Down
7 changes: 3 additions & 4 deletions src/gm3/components/measure/calc.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
* SOFTWARE.
*/

import { getUtmZone } from "../../util";
import { get as getProjection } from "ol/proj";
import { ensureProjection, getUtmZone } from "../../util";
import olLineString from "ol/geom/LineString";

export const getBearing = (pointA, pointB, ordinalDictionary) => {
Expand Down Expand Up @@ -111,7 +110,7 @@ export function getPathSegments(coordinatesLonLat) {
}

// determine an appropriate utm zone for measurement.
const utmZone = getProjection(getUtmZone(coordinatesLonLat[0]));
const utmZone = ensureProjection(getUtmZone(coordinatesLonLat[0]));

const segments = [];
for (let i = 1, ii = coordinatesLonLat.length; i < ii; i++) {
Expand All @@ -131,7 +130,7 @@ export function getPathSegments(coordinatesLonLat) {

export function getSegmentInfo(geom, cursorCoords, isDrawing, ordinalDictionary) {
// determine an appropriate utm zone for measurement.
const utmZone = getProjection(getUtmZone(geom.coordinates[0]));
const utmZone = ensureProjection(getUtmZone(geom.coordinates[0]));

const coords = [].concat(geom.coordinates);

Expand Down
5 changes: 2 additions & 3 deletions src/gm3/jsts.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@

import { BufferOp, GeoJSONReader, GeoJSONWriter } from "turf-jsts";
import turfUnion from "@turf/union";
import * as proj from "ol/proj";
import { jsonToGeom, geomToJson, getUtmZone } from "./util";
import { ensureProjection, jsonToGeom, geomToJson, getUtmZone } from "./util";

export function buffer(feature, meters) {
return bufferFeature(feature, meters).geometry;
Expand All @@ -59,7 +58,7 @@ export function bufferFeature(feature, meters) {
const posPt = getAnchorPoint(feature, [0, 0]);

// find the feature's location in UTM space.
const utmZone = proj.get(getUtmZone(posPt));
const utmZone = ensureProjection(getUtmZone(posPt));

// convert the geometry to an OL geometry
let geom = jsonToGeom(feature.geometry);
Expand Down
56 changes: 27 additions & 29 deletions src/gm3/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@
*/

import Request from "reqwest";
import proj4 from "proj4";

import GeoJSONFormat from "ol/format/GeoJSON";
import { get as getProjection } from "ol/proj";
import { register } from "ol/proj/proj4";

import { featureFilter as createFilter } from "@mapbox/mapbox-gl-style-spec";

Expand Down Expand Up @@ -487,35 +490,6 @@ export function getFeaturesExtent(mapSource) {
return bounds;
}

/* Configure a set of projections useful for GeoMoose.
*
* At this point this will just configure the UTM zones
* as they are used to do accurate measurement and buffers.
*
* @param {Proj4} p4 The Proj4 Library.
*
*/
export function configureProjections(p4) {
for (let utmZone = 1; utmZone <= 60; utmZone++) {
for (const north of ["north", "south"]) {
// southern utm zones are 327XX, northern 326XX
const epsgCode = 32600 + utmZone + (north === "north" ? 0 : 100);

const projId = "EPSG:" + epsgCode;
const projAlias = "UTM" + utmZone + (north === "north" ? "N" : "S");
// it's nice to have a formulary.
const projString =
"+proj=utm +zone=" + utmZone + " +" + north + "+datum=WGS84 +units=m +no_defs";

// set up the standard way of calling the projection
// (using the EPSG Code)
p4.defs(projId, projString);
// add an alias, so it can be referred by 'UTM15N' for example.
p4.defs(projAlias, p4.defs(projId));
}
}
}

/**
* addProjDef
* Add a projection definition
Expand All @@ -528,6 +502,30 @@ export function addProjDef(p4, code, def) {
p4.defs(code, def);
}

export function getUtmProjectionDef(projCode) {
const match = projCode.match(/^UTM([1-9]|[1-5][0-9]|60)([NS])$/);
if (!match) {
return null;
}

const zone = parseInt(match[1], 10);
const north = match[2] === "N" ? "north" : "south";

return "+proj=utm +zone=" + zone + " +" + north + "+datum=WGS84 +units=m +no_defs";
}

export function ensureProjection(projCode, projDef) {
if (!proj4.defs(projCode)) {
const def = projDef || getUtmProjectionDef(projCode);
if (def) {
addProjDef(proj4, projCode, def);
register(proj4);
}
}

return getProjection(projCode);
}

/* Determine the UTM zone for a point
*
* @param {Point-like} An array containing [x,y] in WGS84 or NAD83 DD
Expand Down
4 changes: 0 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ import HashTracker from "./gm3/trackers/hash";
import * as util from "./gm3/util";
import * as jsts from "./gm3/jsts";

import proj4 from "proj4";

util.configureProjections(proj4);

var components = {
Catalog: Catalog,
Map: Map,
Expand Down
8 changes: 1 addition & 7 deletions tests/gm3/components/coordinates.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ import React from "react";
import { render } from "@testing-library/react";
import CoordinateDisplay, { formatCoordinates } from "gm3/components/coordinate-display";

// this is necessary to configure the UTM projections
import { configureProjections } from "gm3/util";
import { register } from "ol/proj/proj4";
import proj4 from "proj4";

describe("coordinate display component", () => {
it("formats coordinates with default precision", () => {
const proj = {
Expand Down Expand Up @@ -63,12 +58,11 @@ describe("coordinate display component", () => {
});

it("accepts a custom projections list", () => {
configureProjections(proj4);
register(proj4);
const projections = [
{
label: "UTM",
ref: "EPSG:32615",
projDef: "+proj=utm +zone=15 +north +datum=WGS84 +units=m +no_defs",
precision: 0,
},
{
Expand Down
19 changes: 0 additions & 19 deletions tests/gm3/components/measure.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ import {
getMeasureLabelStyles,
} from "gm3/components/measure/labels";

// necessary to configure the UTM projections used by getPathSegments
import { configureProjections } from "gm3/util";
import { register } from "ol/proj/proj4";
import proj4 from "proj4";
import LineString from "ol/geom/LineString";
import Polygon from "ol/geom/Polygon";
import { fromLonLat } from "ol/proj";
Expand Down Expand Up @@ -83,11 +79,6 @@ describe("getBearing tests", () => {
*/

describe("getPathSegments tests", () => {
beforeEach(() => {
configureProjections(proj4);
register(proj4);
});

test("returns nothing for paths with fewer than two points", () => {
expect(getPathSegments([])).toEqual([]);
expect(getPathSegments([[0, 45]])).toEqual([]);
Expand Down Expand Up @@ -119,11 +110,6 @@ describe("getPathSegments tests", () => {
*/

describe("getSegmentLabelStyles tests", () => {
beforeEach(() => {
configureProjections(proj4);
register(proj4);
});

test("builds one label per line segment", () => {
const geometry = new LineString([
fromLonLat([-93.0, 45.0]),
Expand Down Expand Up @@ -182,11 +168,6 @@ describe("getComplementaryUnit tests", () => {
});

describe("getAreaLabelStyles tests", () => {
beforeEach(() => {
configureProjections(proj4);
register(proj4);
});

const polygon = new Polygon([
[
[-93.0, 45.0],
Expand Down
10 changes: 0 additions & 10 deletions tests/gm3/jsts.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,7 @@

import * as jsts from "gm3/jsts";

// this is necessary to configure the UTM projections
import { configureProjections } from "gm3/util";
import { register } from "ol/proj/proj4";
import proj4 from "proj4";

describe("test basic jsts stuff", function () {
beforeEach(() => {
configureProjections(proj4);
register(proj4);
});

it("buffers a point", function () {
const point = {
type: "Feature",
Expand Down
18 changes: 18 additions & 0 deletions tests/gm3/util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,24 @@ test("getUtmZone", () => {
expect(util.getUtmZone([-93, 45])).toBe("UTM15N");
});

test("getUtmProjectionDef", () => {
expect(util.getUtmProjectionDef("UTM15N")).toBe(
"+proj=utm +zone=15 +north+datum=WGS84 +units=m +no_defs"
);
expect(util.getUtmProjectionDef("UTM21S")).toBe(
"+proj=utm +zone=21 +south+datum=WGS84 +units=m +no_defs"
);
});

test("getUtmProjectionDef anti-cases", () => {
expect(util.getUtmProjectionDef("UTM0N")).toBe(null);
expect(util.getUtmProjectionDef("UTM61N")).toBe(null);
expect(util.getUtmProjectionDef("UTM15")).toBe(null);
expect(util.getUtmProjectionDef("UTM15n")).toBe(null);
expect(util.getUtmProjectionDef("EPSG:32615")).toBe(null);
expect(util.getUtmProjectionDef("foo")).toBe(null);
});

test("metersLengthToUnits", () => {
expect(util.metersLengthToUnits(1, "ft")).toBe(1 / 0.3048);
expect(util.metersLengthToUnits(1, "mi")).toBe(1 / 1609.347);
Expand Down
Loading