162 lines
4.2 KiB
JavaScript
162 lines
4.2 KiB
JavaScript
//index.js
|
|
var deepEqual = require('deep-equal');
|
|
|
|
var Equality = function(opt) {
|
|
this.precision = opt && opt.precision ? opt.precision : 17;
|
|
this.direction = opt && opt.direction ? opt.direction : false;
|
|
this.pseudoNode = opt && opt.pseudoNode ? opt.pseudoNode : false;
|
|
this.objectComparator = opt && opt.objectComparator ? opt.objectComparator : objectComparator;
|
|
};
|
|
|
|
Equality.prototype.compare = function(g1,g2) {
|
|
if (g1.type !== g2.type || !sameLength(g1,g2)) return false;
|
|
|
|
switch(g1.type) {
|
|
case 'Point':
|
|
return this.compareCoord(g1.coordinates, g2.coordinates);
|
|
break;
|
|
case 'LineString':
|
|
return this.compareLine(g1.coordinates, g2.coordinates,0,false);
|
|
break;
|
|
case 'Polygon':
|
|
return this.comparePolygon(g1,g2);
|
|
break;
|
|
case 'Feature':
|
|
return this.compareFeature(g1, g2);
|
|
default:
|
|
if (g1.type.indexOf('Multi') === 0) {
|
|
var context = this;
|
|
var g1s = explode(g1);
|
|
var g2s = explode(g2);
|
|
return g1s.every(function(g1part) {
|
|
return this.some(function(g2part) {
|
|
return context.compare(g1part,g2part);
|
|
});
|
|
},g2s);
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
function explode(g) {
|
|
return g.coordinates.map(function(part) {
|
|
return {
|
|
type: g.type.replace('Multi', ''),
|
|
coordinates: part}
|
|
});
|
|
}
|
|
//compare length of coordinates/array
|
|
function sameLength(g1,g2) {
|
|
return g1.hasOwnProperty('coordinates') ?
|
|
g1.coordinates.length === g2.coordinates.length
|
|
: g1.length === g2.length;
|
|
}
|
|
|
|
// compare the two coordinates [x,y]
|
|
Equality.prototype.compareCoord = function(c1,c2) {
|
|
if (c1.length !== c2.length) {
|
|
return false;
|
|
}
|
|
|
|
for (var i=0; i < c1.length; i++) {
|
|
if (c1[i].toFixed(this.precision) !== c2[i].toFixed(this.precision)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
Equality.prototype.compareLine = function(path1,path2,ind,isPoly) {
|
|
if (!sameLength(path1,path2)) return false;
|
|
var p1 = this.pseudoNode ? path1 : this.removePseudo(path1);
|
|
var p2 = this.pseudoNode ? path2 : this.removePseudo(path2);
|
|
if (isPoly && !this.compareCoord(p1[0],p2[0])) {
|
|
// fix start index of both to same point
|
|
p2 = this.fixStartIndex(p2,p1);
|
|
if(!p2) return;
|
|
}
|
|
// for linestring ind =0 and for polygon ind =1
|
|
var sameDirection = this.compareCoord(p1[ind],p2[ind]);
|
|
if (this.direction || sameDirection
|
|
) {
|
|
return this.comparePath(p1, p2);
|
|
} else {
|
|
if (this.compareCoord(p1[ind],p2[p2.length - (1+ind)])
|
|
) {
|
|
return this.comparePath(p1.slice().reverse(), p2);
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
Equality.prototype.fixStartIndex = function(sourcePath,targetPath) {
|
|
//make sourcePath first point same as of targetPath
|
|
var correctPath,ind = -1;
|
|
for (var i=0; i< sourcePath.length; i++) {
|
|
if(this.compareCoord(sourcePath[i],targetPath[0])) {
|
|
ind = i;
|
|
break;
|
|
}
|
|
}
|
|
if (ind >= 0) {
|
|
correctPath = [].concat(
|
|
sourcePath.slice(ind,sourcePath.length),
|
|
sourcePath.slice(1,ind+1));
|
|
}
|
|
return correctPath;
|
|
};
|
|
Equality.prototype.comparePath = function (p1,p2) {
|
|
var cont = this;
|
|
return p1.every(function(c,i) {
|
|
return cont.compareCoord(c,this[i]);
|
|
},p2);
|
|
};
|
|
|
|
Equality.prototype.comparePolygon = function(g1,g2) {
|
|
if (this.compareLine(g1.coordinates[0],g2.coordinates[0],1,true)) {
|
|
var holes1 = g1.coordinates.slice(1,g1.coordinates.length);
|
|
var holes2 = g2.coordinates.slice(1,g2.coordinates.length);
|
|
var cont = this;
|
|
return holes1.every(function(h1) {
|
|
return this.some(function(h2) {
|
|
return cont.compareLine(h1,h2,1,true);
|
|
});
|
|
},holes2);
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
Equality.prototype.compareFeature = function(g1,g2) {
|
|
if (
|
|
g1.id !== g2.id ||
|
|
!this.objectComparator(g1.properties, g2.properties) ||
|
|
!this.compareBBox(g1,g2)
|
|
) {
|
|
return false;
|
|
}
|
|
return this.compare(g1.geometry, g2.geometry);
|
|
};
|
|
|
|
Equality.prototype.compareBBox = function(g1,g2) {
|
|
if (
|
|
(!g1.bbox && !g2.bbox) ||
|
|
(
|
|
g1.bbox && g2.bbox &&
|
|
this.compareCoord(g1.bbox, g2.bbox)
|
|
)
|
|
) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
Equality.prototype.removePseudo = function(path) {
|
|
//TODO to be implement
|
|
return path;
|
|
};
|
|
|
|
function objectComparator(obj1, obj2) {
|
|
return deepEqual(obj1, obj2, {strict: true});
|
|
}
|
|
|
|
module.exports = Equality;
|