Skip to content

Commit 3fd911f

Browse files
committed
Expose single point type for both 2D and 3D
With optional `z` component. This is more consistent with Cypher, that does not differentiate between 2D and 3D points. It has only a single overloaded `point()` function.
1 parent d7aea67 commit 3fd911f

File tree

6 files changed

+61
-93
lines changed

6 files changed

+61
-93
lines changed

src/v1/index.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import VERSION from '../version';
2929
import {assertString, isEmptyObjectOrNull} from './internal/util';
3030
import urlUtil from './internal/url-util';
3131
import HttpDriver from './internal/http/http-driver';
32-
import {Point2D, Point3D} from './spatial-types';
32+
import {Point} from './spatial-types';
3333

3434
/**
3535
* @property {function(username: string, password: string, realm: ?string)} basic the function to create a
@@ -207,8 +207,7 @@ const types = {
207207
Result,
208208
ResultSummary,
209209
Record,
210-
Point2D,
211-
Point3D
210+
Point
212211
};
213212

214213
/**

src/v1/internal/packstream-v2.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
import * as v1 from './packstream-v1';
21-
import {isPoint2D, isPoint3D, Point2D, Point3D} from '../spatial-types';
21+
import {isPoint, Point} from '../spatial-types';
2222
import {int} from '../integer';
2323

2424
const POINT_2D = 0x58;
@@ -39,10 +39,8 @@ export class Packer extends v1.Packer {
3939
}
4040

4141
packable(obj, onError) {
42-
if (isPoint2D(obj)) {
43-
return () => packPoint2D(obj, this, onError);
44-
} else if (isPoint3D(obj)) {
45-
return () => packPoint3D(obj, this, onError);
42+
if (isPoint(obj)) {
43+
return () => packPoint(obj, this, onError);
4644
} else {
4745
return super.packable(obj, onError);
4846
}
@@ -71,6 +69,15 @@ export class Unpacker extends v1.Unpacker {
7169
}
7270
}
7371

72+
function packPoint(point, packer, onError) {
73+
const is2DPoint = point.z === null || point.z === undefined;
74+
if (is2DPoint) {
75+
packPoint2D(point, packer, onError);
76+
} else {
77+
packPoint3D(point, packer, onError);
78+
}
79+
}
80+
7481
function packPoint2D(point, packer, onError) {
7582
const packableStructFields = [
7683
packer.packable(int(point.srid), onError),
@@ -91,15 +98,16 @@ function packPoint3D(point, packer, onError) {
9198
}
9299

93100
function unpackPoint2D(unpacker, buffer) {
94-
return new Point2D(
101+
return new Point(
95102
unpacker.unpack(buffer), // srid
96103
unpacker.unpack(buffer), // x
97-
unpacker.unpack(buffer) // y
104+
unpacker.unpack(buffer), // y
105+
undefined // z
98106
);
99107
}
100108

101109
function unpackPoint3D(unpacker, buffer) {
102-
return new Point3D(
110+
return new Point(
103111
unpacker.unpack(buffer), // srid
104112
unpacker.unpack(buffer), // x
105113
unpacker.unpack(buffer), // y

src/v1/spatial-types.js

Lines changed: 9 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,44 +19,19 @@
1919

2020
import {int} from './integer';
2121

22-
const POINT_2D_IDENTIFIER_PROPERTY = '__isPoint2D__';
23-
const POINT_3D_IDENTIFIER_PROPERTY = '__isPoint3D__';
22+
const POINT_IDENTIFIER_PROPERTY = '__isPoint__';
2423

2524
/**
26-
* Represents a single two-dimensional point in a particular coordinate reference system.
25+
* Represents a single two or three-dimensional point in a particular coordinate reference system.
2726
*/
28-
export class Point2D {
27+
export class Point {
2928

3029
/**
3130
* @constructor
3231
* @param {number|Integer} srid the coordinate reference system identifier.
3332
* @param {number} x the <code>x</code> coordinate of the point.
3433
* @param {number} y the <code>y</code> coordinate of the point.
35-
*/
36-
constructor(srid, x, y) {
37-
this.srid = int(srid);
38-
this.x = x;
39-
this.y = y;
40-
}
41-
}
42-
43-
Object.defineProperty(Point2D.prototype, POINT_2D_IDENTIFIER_PROPERTY, {
44-
value: true,
45-
enumerable: false,
46-
configurable: false
47-
});
48-
49-
/**
50-
* Represents a single tree-dimensional point in a particular coordinate reference system.
51-
*/
52-
export class Point3D {
53-
54-
/**
55-
* @constructor
56-
* @param {number|Integer} srid the coordinate reference system identifier.
57-
* @param {number} x the <code>x</code> coordinate of the point.
58-
* @param {number} y the <code>y</code> coordinate of the point.
59-
* @param {number} z the <code>z</code> coordinate of the point.
34+
* @param {number|undefined} z the <code>y</code> coordinate of the point or <code>undefined</code> if point has 2 dimensions.
6035
*/
6136
constructor(srid, x, y, z) {
6237
this.srid = int(srid);
@@ -66,30 +41,17 @@ export class Point3D {
6641
}
6742
}
6843

69-
Object.defineProperty(Point3D.prototype, POINT_3D_IDENTIFIER_PROPERTY, {
44+
Object.defineProperty(Point.prototype, POINT_IDENTIFIER_PROPERTY, {
7045
value: true,
7146
enumerable: false,
7247
configurable: false
7348
});
7449

7550
/**
76-
* Test if given object is an instance of {@link Point2D} class.
51+
* Test if given object is an instance of {@link Point} class.
7752
* @param {object} obj the object to test.
78-
* @return {boolean} <code>true</code> if given object is a {@link Point2D}, <code>false</code> otherwise.
53+
* @return {boolean} <code>true</code> if given object is a {@link Point}, <code>false</code> otherwise.
7954
*/
80-
export function isPoint2D(obj) {
81-
return hasProperty(obj, POINT_2D_IDENTIFIER_PROPERTY);
82-
}
83-
84-
/**
85-
* Test if given object is an instance of {@link Point3D} class.
86-
* @param {object} obj the object to test.
87-
* @return {boolean} <code>true</code> if given object is a {@link Point3D}, <code>false</code> otherwise.
88-
*/
89-
export function isPoint3D(obj) {
90-
return hasProperty(obj, POINT_3D_IDENTIFIER_PROPERTY);
91-
}
92-
93-
function hasProperty(obj, name) {
94-
return (obj && obj[name]) === true;
55+
export function isPoint(obj) {
56+
return (obj && obj[POINT_IDENTIFIER_PROPERTY]) === true;
9557
}

test/types/v1/spatial-types.test.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,30 @@
1717
* limitations under the License.
1818
*/
1919

20-
import {Point2D, Point3D} from "../../../types/v1/spatial-types";
20+
import {isPoint, Point} from "../../../types/v1/spatial-types";
2121
import Integer, {int} from "../../../types/v1/integer";
2222

23-
const point1: Point2D = new Point2D(int(1), 2, 3);
23+
const point1: Point = new Point(int(1), 2, 3);
2424
const srid1: Integer = point1.srid;
2525
const x1: number = point1.x;
2626
const y1: number = point1.y;
2727

28-
const point2: Point2D<number> = new Point2D(1, 2, 3);
28+
const point2: Point<number> = new Point(1, 2, 3);
2929
const srid2: number = point2.srid;
3030
const x2: number = point2.x;
3131
const y2: number = point2.y;
3232

33-
const point3: Point3D = new Point3D(int(1), 2, 3, 4);
33+
const point3: Point = new Point(int(1), 2, 3, 4);
3434
const srid3: Integer = point3.srid;
3535
const x3: number = point3.x;
3636
const y3: number = point3.y;
3737
const z3: number = point3.z;
3838

39-
const point4: Point3D<number> = new Point3D(1, 2, 3, 4);
39+
const point4: Point<number> = new Point(1, 2, 3, 4);
4040
const srid4: number = point4.srid;
4141
const x4: number = point4.x;
4242
const y4: number = point4.y;
4343
const z4: number = point4.z;
44+
45+
const isPoint1: boolean = isPoint(point1);
46+
const isPoint2: boolean = isPoint(null);

test/v1/spatial-types.test.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import neo4j from '../../src/v1';
2121
import sharedNeo4j from '../internal/shared-neo4j';
2222
import {ServerVersion, VERSION_3_4_0} from '../../src/v1/internal/server-version';
23-
import {isPoint2D, isPoint3D, Point2D, Point3D} from '../../src/v1/spatial-types';
23+
import {isPoint, Point} from '../../src/v1/spatial-types';
2424

2525
const WGS_84_2D_CRS_CODE = neo4j.int(4326);
2626
const CARTESIAN_2D_CRS_CODE = neo4j.int(7203);
@@ -67,25 +67,27 @@ describe('spatial-types', () => {
6767

6868
it('should receive 2D points', done => {
6969
testReceivingOfPoints(done, 'RETURN point({x: 169.99, y: 12.1718})', point => {
70-
expect(isPoint2D(point)).toBeTruthy();
70+
expect(isPoint(point)).toBeTruthy();
7171
expect(point.srid).toEqual(CARTESIAN_2D_CRS_CODE);
7272
expect(point.x).toEqual(169.99);
7373
expect(point.y).toEqual(12.1718);
74+
expect(point.z).toBeUndefined();
7475
});
7576
});
7677

7778
it('should receive 2D points with crs', done => {
7879
testReceivingOfPoints(done, `RETURN point({x: 2.3, y: 4.5, crs: 'WGS-84'})`, point => {
79-
expect(isPoint2D(point)).toBeTruthy();
80+
expect(isPoint(point)).toBeTruthy();
8081
expect(point.srid).toEqual(WGS_84_2D_CRS_CODE);
8182
expect(point.x).toEqual(2.3);
8283
expect(point.y).toEqual(4.5);
84+
expect(point.z).toBeUndefined();
8385
});
8486
});
8587

8688
it('should receive 3D points', done => {
8789
testReceivingOfPoints(done, 'RETURN point({x: -19.9, y: 45.99, z: 8.88})', point => {
88-
expect(isPoint3D(point)).toBeTruthy();
90+
expect(isPoint(point)).toBeTruthy();
8991
expect(point.srid).toEqual(CARTESIAN_3D_CRS_CODE);
9092
expect(point.x).toEqual(-19.9);
9193
expect(point.y).toEqual(45.99);
@@ -95,7 +97,7 @@ describe('spatial-types', () => {
9597

9698
it('should receive 3D points with crs', done => {
9799
testReceivingOfPoints(done, `RETURN point({x: 34.76, y: 11.9, z: -99.01, crs: 'WGS-84-3D'})`, point => {
98-
expect(isPoint3D(point)).toBeTruthy();
100+
expect(isPoint(point)).toBeTruthy();
99101
expect(point.srid).toEqual(WGS_84_3D_CRS_CODE);
100102
expect(point.x).toEqual(34.76);
101103
expect(point.y).toEqual(11.9);
@@ -104,33 +106,33 @@ describe('spatial-types', () => {
104106
});
105107

106108
it('should send and receive 2D point', done => {
107-
testSendingAndReceivingOfPoints(done, new Point2D(CARTESIAN_2D_CRS_CODE, 19.101, -88.21));
109+
testSendingAndReceivingOfPoints(done, new Point(CARTESIAN_2D_CRS_CODE, 19.101, -88.21));
108110
});
109111

110112
it('should send and receive 3D point', done => {
111-
testSendingAndReceivingOfPoints(done, new Point3D(WGS_84_3D_CRS_CODE, 1.22, 9.8, -6.65));
113+
testSendingAndReceivingOfPoints(done, new Point(WGS_84_3D_CRS_CODE, 1.22, 9.8, -6.65));
112114
});
113115

114116
it('should send and receive array of 2D points', done => {
115117
const arrayOfPoints = [
116-
new Point2D(WGS_84_2D_CRS_CODE, 12.3, 11.2),
117-
new Point2D(WGS_84_2D_CRS_CODE, 2.45, 91.302),
118-
new Point2D(WGS_84_2D_CRS_CODE, 0.12, -99.9),
119-
new Point2D(WGS_84_2D_CRS_CODE, 93.75, 123.213),
120-
new Point2D(WGS_84_2D_CRS_CODE, 111.13, -90.1),
121-
new Point2D(WGS_84_2D_CRS_CODE, 43.99, -1)
118+
new Point(WGS_84_2D_CRS_CODE, 12.3, 11.2),
119+
new Point(WGS_84_2D_CRS_CODE, 2.45, 91.302),
120+
new Point(WGS_84_2D_CRS_CODE, 0.12, -99.9),
121+
new Point(WGS_84_2D_CRS_CODE, 93.75, 123.213),
122+
new Point(WGS_84_2D_CRS_CODE, 111.13, -90.1),
123+
new Point(WGS_84_2D_CRS_CODE, 43.99, -1)
122124
];
123125

124126
testSendingAndReceivingOfPoints(done, arrayOfPoints);
125127
});
126128

127129
it('should send and receive array of 3D points', done => {
128130
const arrayOfPoints = [
129-
new Point3D(CARTESIAN_3D_CRS_CODE, 83.38, 123.9, -19),
130-
new Point3D(CARTESIAN_3D_CRS_CODE, 31, 39.1, -19.19),
131-
new Point3D(CARTESIAN_3D_CRS_CODE, 0.845, -0.74, 3.48),
132-
new Point3D(CARTESIAN_3D_CRS_CODE, 123.33, 93.3, 96.96),
133-
new Point3D(CARTESIAN_3D_CRS_CODE, -54.9, 13.7893, -90.9)
131+
new Point(CARTESIAN_3D_CRS_CODE, 83.38, 123.9, -19),
132+
new Point(CARTESIAN_3D_CRS_CODE, 31, 39.1, -19.19),
133+
new Point(CARTESIAN_3D_CRS_CODE, 0.845, -0.74, 3.48),
134+
new Point(CARTESIAN_3D_CRS_CODE, 123.33, 93.3, 96.96),
135+
new Point(CARTESIAN_3D_CRS_CODE, -54.9, 13.7893, -90.9)
134136
];
135137

136138
testSendingAndReceivingOfPoints(done, arrayOfPoints);

types/v1/spatial-types.d.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,18 @@
2020
import {NumberOrInteger} from './graph-types';
2121
import Integer from "./integer";
2222

23-
declare class Point2D<T extends NumberOrInteger = Integer> {
23+
declare class Point<T extends NumberOrInteger = Integer> {
2424
srid: T;
2525
x: number;
2626
y: number;
27+
z: number | undefined;
2728

28-
constructor(srid: T, x: number, y: number)
29+
constructor(srid: T, x: number, y: number, z?: number | undefined)
2930
}
3031

31-
declare class Point3D<T extends NumberOrInteger = Integer> {
32-
srid: T;
33-
x: number;
34-
y: number;
35-
z: number;
36-
37-
constructor(srid: T, x: number, y: number, z: number)
38-
}
32+
declare function isPoint(obj: object): boolean;
3933

4034
export {
41-
Point2D,
42-
Point3D
35+
Point,
36+
isPoint
4337
}

0 commit comments

Comments
 (0)