[Mapbender-commits] r3205 - branches/noframes/http/javascripts
svn_mapbender at osgeo.org
svn_mapbender at osgeo.org
Fri Nov 7 05:21:36 EST 2008
Author: christoph
Date: 2008-11-07 05:21:35 -0500 (Fri, 07 Nov 2008)
New Revision: 3205
Modified:
branches/noframes/http/javascripts/geometry.js
Log:
merged from trunk...now supports multigeometries and enclaves
Modified: branches/noframes/http/javascripts/geometry.js
===================================================================
--- branches/noframes/http/javascripts/geometry.js 2008-11-07 10:19:04 UTC (rev 3204)
+++ branches/noframes/http/javascripts/geometry.js 2008-11-07 10:21:35 UTC (rev 3205)
@@ -102,8 +102,11 @@
* @type Point
* @returns the Point object at the given indices
*/
-GeometryArray.prototype.getPoint = function(i,j,k){
- return this.get(i).get(j).get(k);
+GeometryArray.prototype.getPoint = function(i, j, k, l){
+ if (l == undefined) {
+ return this.get(i).get(j).get(k);
+ }
+ return this.get(i).get(j).innerRings.get(k).get(l);
};
/**
@@ -128,7 +131,9 @@
* @param {Integer} j index of the Geometry
*/
GeometryArray.prototype.delGeometry = function(i,j){
- if (this.get(i).del(j) === false) {this.del(i);}
+ if (this.get(i).del(j) === false) {
+ this.del(i);
+ }
};
/**
@@ -138,9 +143,11 @@
* @param {Integer} j index of the Geometry
* @param {Integer} k index of the Point
*/
-GeometryArray.prototype.delPoint = function (i,j,k){
- var res = this.get(i).delPoint(j,k);
- if (res === false) {this.del(i);}
+GeometryArray.prototype.delPoint = function (i, j, k, l) {
+ var res = this.get(i).delPoint(j, k, l);
+ if (res === false) {
+ this.del(i);
+ }
};
/**
@@ -152,8 +159,12 @@
this.delGeometry(-1, -1);
}
else {
- if (this.get(-1).get(-1).count() === 0) {this.get(-1).del(-1);}
- if (this.get(-1).count() === 0) {this.del(-1);}
+ if (this.get(-1).get(-1).count() === 0) {
+ this.get(-1).del(-1);
+ }
+ if (this.get(-1).count() === 0) {
+ this.del(-1);
+ }
}
};
@@ -169,6 +180,22 @@
finished = true;
for (var i = 0 ; finished === true && i < this.count() ; i++){
for (var j = 0 ; finished === true && j < this.get(i).count() ; j++){
+
+ var currentGeometry = this.get(i).get(j);
+ if (currentGeometry.geomType == geomType.polygon && currentGeometry.innerRings) {
+ for (var k = 0; finished === true && k < currentGeometry.innerRings.count(); k++) {
+ for (var l = 0; finished === true && l < currentGeometry.innerRings.get(k).count(); l++) {
+ if (this.getPoint(i, j, k, l).equals(point)) {
+ this.delPoint(i, j, k, l);
+ finished = false;
+ }
+ }
+ }
+ }
+ if (!finished) {
+ break;
+ }
+
for (var k = 0 ; finished === true && k < this.get(i).get(j).count() ; k++){
if (this.getPoint(i,j,k).equals(point)){
this.delPoint(i,j,k);
@@ -247,36 +274,37 @@
var geometryType = tmpArray[0];
switch (geometryType) {
- case "POLYGON":
- var text = text.replace(/\)/, "");
- text = text.replace(/\(\(/, "(");
- var tmpArray = text.split("(");
-
- var coordinatesArray = tmpArray[1].split(",");
-
- this.addMember(geomType.polygon);
- this.get(-1).addGeometry();
- for (var m = 0; m < -1 + coordinatesArray.length; m++) {
- var currentPoint = coordinatesArray[m].split(" ");
- this.getGeometry(-1, -1).addPointByCoordinates(parseFloat(currentPoint[0]), parseFloat(currentPoint[1]));
- }
- this.close();
- break;
case "MULTIPOLYGON":
- var text = text.replace(/\)/, "");
- text = text.replace(/\(\(\(/, "(");
-
- var tmpArray = text.split("(");
-
- var coordinatesArray = tmpArray[1].split(",");
-
+ var text = text.replace(/\)/g, "");
+ var sepArray = text.split("(((");
+ var polyArray = sepArray[1].split(",((");
+
this.addMember(geomType.polygon);
- this.get(-1).addGeometry();
- for (var m = 0; m < -1 + coordinatesArray.length; m++) {
- var currentPoint = coordinatesArray[m].split(" ");
- this.getGeometry(-1, -1).addPointByCoordinates(parseFloat(currentPoint[0]), parseFloat(currentPoint[1]));
+ for (var i = 0; i < polyArray.length; i++) {
+ var ringArray = polyArray[i].split(",(");
+ for (var j = 0; j < ringArray.length; j++) {
+ var coordinatesArray = ringArray[j].split(",");
+ if (j === 0) {
+ // add outer ring
+ this.get(-1).addGeometry();
+ for (var m = 0; m < -1 + coordinatesArray.length; m++) {
+ var currentPoint = coordinatesArray[m].split(" ");
+ this.getGeometry(-1, -1).addPointByCoordinates(parseFloat(currentPoint[0]), parseFloat(currentPoint[1]));
+ }
+ this.close();
+ }
+ else {
+ // add inner ring
+ var ring = new Geometry(geomType.polygon);
+ for (var m = 0; m < -1 + coordinatesArray.length; m++) {
+ var currentPoint = coordinatesArray[m].split(" ");
+ ring.addPointByCoordinates(parseFloat(currentPoint[0]), parseFloat(currentPoint[1]));
+ }
+ ring.close();
+ this.getGeometry(-1,-1).addInnerRing(ring);
+ }
+ }
}
- this.close();
break;
}
};
@@ -533,7 +561,6 @@
var tmpLength = this.count() - 1;
for (var z = i; z < tmpLength ; z ++){
this.list[z] = this.list[z+1];
- e[z] = e[z+1];
}
this.list.length -= 1;
if (this.list.length === 0) {return false;}
@@ -661,9 +688,20 @@
* @return true if the deletion succeded; else false.
* @type Boolean
*/
-MultiGeometry.prototype.delPoint = function(i,j){
- var res = this.get(i).del(j);
- if (res === false) {return this.del(i);}
+MultiGeometry.prototype.delPoint = function(i, j, k){
+ var res;
+ if (k == undefined) {
+ res = this.get(i).del(j);
+ if (res === false) {
+ return this.del(i);
+ }
+ }
+ else {
+ res = this.get(i).innerRings.get(j).del(k);
+ if (res === false) {
+ this.get(i).innerRings.del(j);
+ }
+ }
return true;
};
@@ -679,27 +717,20 @@
var numOfGeom = this.count();
if (numOfGeom >= 1) {
if (this.geomType == geomType.polygon) {
- text += "POLYGON (";
-
- for (var i = 0; i < this.count(); i++) {
- if (i > 0) {
- text += ", ";
- }
- text += "(";
-
- var currentPolygon = this.get(i);
- for (var j = 0; j < currentPolygon.count(); j++) {
- if (j > 0) {
+ if (numOfGeom > 1) {
+ text += "MULTIPOLYGON (";
+ for (var i = 0; i < numOfGeom; i++) {
+ if (i > 0) {
text += ", ";
}
-
- var currentPoint = currentPolygon.get(j);
- text += currentPoint.x + " " + currentPoint.y
+ var currentPolygon = this.get(i);
+ text += "(" + currentPolygon.toText() + ")";
}
-
text += ")";
}
- text += ")";
+ else {
+ text += "POLYGON (" + this.get(0).toText() + ")";
+ }
}
else if (this.geomType == geomType.line) {
text += "LINESTRING (";
@@ -780,6 +811,13 @@
return false;
};
+
+function InnerRings () {
+ this.list = [];
+};
+
+InnerRings.prototype = new List();
+
/**
* @class a Geometry is a List of Point objects. If it is a polygon, the last point has
* to equal the first point.
@@ -988,10 +1026,44 @@
this.geomType = aGeomtype;
this.name = nameGeometry;
+
+ // add these members if the geometry is a polygon
+ if (this.geomType == geomType.polygon) {
+ this.innerRings = new InnerRings();
+ this.addInnerRing = function (somePolygon) {
+ this.innerRings.add(somePolygon);
+ };
+ this.delInnerRing = function (index) {
+ this.innerRings.del(index);
+ };
+ }
}
Geometry.prototype = new List();
+Geometry.prototype.toText = function () {
+ var text = "";
+ switch (this.geomType) {
+ case geomType.polygon:
+ text += "(";
+ for (var j = 0; j < this.count(); j++) {
+ if (j > 0) {
+ text += ", ";
+ }
+ var currentPoint = this.get(j);
+ text += currentPoint.x + " " + currentPoint.y
+ }
+ text += ")";
+ if (this.innerRings && this.innerRings.count() > 0) {
+ for (var k = 0; k < this.innerRings.count(); k++) {
+ text += ", ";
+ text += this.innerRings.get(k).toText();
+ }
+ }
+ break;
+ }
+ return text;
+};
/**
* gets the bounding box of this {@link Geometry}
*
@@ -1010,6 +1082,19 @@
if (pos.y < min.y) {min.y = pos.y;}
else if (pos.y > max.y) {max.y = pos.y;}
}
+ if (this.geomType == geomType.polygon) {
+ for (var i = 0; i < this.innerRings.count(); i++) {
+ var currentRing = this.innerRings.get(i);
+ for (var j=0; j<currentRing.count(); j++){
+ var pos = currentRing.get(j);
+ if (pos.x < min.x) {min.x = pos.x;}
+ else if (pos.x > max.x) {max.x = pos.x;}
+ if (pos.y < min.y) {min.y = pos.y;}
+ else if (pos.y > max.y) {max.y = pos.y;}
+ }
+ }
+ }
+
return [min, max];
};
@@ -1031,6 +1116,22 @@
else {this.updatePointAtIndex(newP, i);}
}
}
+ if (this.geomType == geomType.polygon) {
+ for (var j = 0; j < this.innerRings.count(); j++) {
+ var len = this.innerRings.get(j).count();
+ for (var i = 0; i < len ; i++){
+ if (oldP.equals(this.innerRings.get(j).get(i))){
+ if (i>0 && newP.equals(this.innerRings.get(j).get(i-1))){
+ this.innerRings.get(j).del(i);
+ len--;
+ i--;
+ }
+ else {this.innerRings.get(j).updatePointAtIndex(newP, i);}
+ }
+ }
+
+ }
+ }
};
/**
@@ -1046,9 +1147,130 @@
for (var i=0; i < this.count(); i++) {
if (!this.get(i).equals(geom.get(i))) {return false;}
}
+ if (!this.innerRings && !geom.innerRings) {
+ // no inner rings; fine
+ }
+ else if (this.innerRings && geom.innerRings) {
+ if (this.innerRings.count() != geom.innerRings.count()) {
+ return false;
+ }
+ for (var j = 0; j < this.innerRings.count(); j++) {
+ if (!this.innerRings.get(j).equals(geom.innerRings.get(j))) {
+ return false;
+ }
+ }
+ }
+ else {
+ // inner ring mismatch
+ return false;
+ }
return true;
};
+/**
+ * creates a polygon geometry object which form a buffer around the line geometry
+ *
+ * @param {float} real world units to buffer around the line
+ * @param {float} (optional) units to buffer around the line in Y direction
+ *
+ * @return linebuffer polygon
+ * @type Geometry
+ */
+Geometry.prototype.bufferLine = function(bufferX, bufferY){
+ if(typeof(bufferY)=='undefined')
+ bufferY = bufferX;
+ if(this.geomType!=geomType.line || this.count()<2)
+ return false;
+
+ var ret = new Geometry(geomType.polygon)
+
+ //get vector from point 0 to point 1
+ last_vec = this.get(1).minus(this.get(0));
+
+ //get 90° rotated vector
+ last_vec_o = new Point(-last_vec.y, last_vec.x);
+
+ //resize vectors with apropriate linebuffer length
+ last_vec_o = last_vec_o.dividedBy(last_vec_o.dist(new Point(0,0)));
+ last_vec_o.x*=bufferX; last_vec_o.y*=bufferY;
+ last_vec = last_vec.dividedBy(last_vec.dist(new Point(0,0)));
+ last_vec.x*=bufferX; last_vec.y*=bufferY;
+
+ //add first pointsets
+ ret.list.unshift(this.get(0).plus(last_vec_o).minus(last_vec));
+ ret.list.push(this.get(0).minus(last_vec_o).minus(last_vec));
+
+ for(var i=1;i<this.count()-1;i++){
+ //get vector from point n to point n+1
+ vec = this.get(i+1).minus(this.get(i));
+ //get orthogonal (90° rotated) vector
+ vec_o = new Point(-vec.y, vec.x);
+
+ //resize vectors to linebuffer length
+ vec_o = vec_o.dividedBy(vec_o.dist(new Point(0,0)));
+ vec_o.x*=bufferX; vec_o.y*=bufferY;
+ vec = vec.dividedBy(vec.dist(new Point(0,0)));
+ vec.x*=bufferX; vec.y*=bufferY;
+
+ //if direction is the same continue
+ if(vec.equals(last_vec))
+ continue;
+
+ // calculate directed angle between the two vectors by
+ // calculating the argument diffenrences between complex numbers
+ // arg(x + i*y) (because law of cosine can onlycalculate undirected angle)
+ var angle = (Math.atan2(vec.x,vec.y)-Math.atan2(last_vec.x,last_vec.y))
+ //ensure that angle is -180<=angle<=180
+ if(angle<-Math.PI)angle=2*Math.PI+angle;
+ if(angle>+Math.PI)angle=2*Math.PI-angle;
+
+ //calculate the distance between the next points on boundary
+ //and the line point
+ //the point will be in the direction of angle/2 relative to last_vec_o
+ //since cosine is adjacent side / hypothenuse and we know that
+ //the adjacent side is lineBuffer the hypothenus (our distance) is
+ var ndist = 1/(Math.cos(angle/2))
+ //direction of next points on boundary
+ var int_vec = vec_o.plus(last_vec_o);
+ //resize direction vector to our distance
+ int_vec = int_vec.times(ndist/int_vec.dist(new Point(0,0)));
+ int_vec.x*=bufferX; int_vec.y*=bufferY;
+
+ //look if we have an outer sharp corner (>90°)
+ if(angle>Math.PI/2){
+ //push cutted edge points
+ ret.list.unshift(this.get(i).plus(last_vec_o).plus(last_vec));
+ ret.list.unshift(this.get(i).plus(vec_o).minus(vec));
+ }
+ else{
+ //push inner/light edge
+ ret.list.unshift(this.get(i).plus(int_vec));
+ }
+
+ //look if we have an inner sharp corner (<-90°)
+ if(angle<-Math.PI/2){
+ //push cutted edge points
+ ret.list.push(this.get(i).minus(last_vec_o).plus(last_vec));
+ ret.list.push(this.get(i).minus(vec_o).minus(vec));
+ }
+ else{
+ //push inner/light edge
+ ret.list.push(this.get(i).minus(int_vec));
+ }
+
+ //copy for next point
+ last_vec = vec;
+ last_vec_o = vec_o;
+ }
+ //add last pointsets
+ ret.list.unshift(this.get(i).plus(last_vec_o).plus(last_vec));
+ ret.list.push(this.get(i).minus(last_vec_o).plus(last_vec));
+
+ ret.close();
+
+ return ret;
+}
+
Geometry.prototype.toString = function () {
var str = "";
@@ -1066,6 +1288,20 @@
}
str += this.get(i).toString();
}
+
+ if (typeof(this.innerRings) == "object" && this.innerRings.count() > 0) {
+ for (var j = 0; j < this.innerRings.count(); j++) {
+ var currentRing = this.innerRings.get(j);
+
+ str += "],[";
+ for (var i = 0; i < currentRing.count(); i++) {
+ if (i > 0) {
+ str += ", ";
+ }
+ str += currentRing.get(i).toString();
+ }
+ }
+ }
str += "]]}";
}
else if (this.geomType == geomType.line) {
@@ -1272,6 +1508,26 @@
else if(t == geomType.line || t==geomType.polygon) {
for(var i=0, ilen = g.count(); i < ilen; i++){
var currentGeom = g.get(i);
+ // paint inner rings
+ if (t==geomType.polygon && currentGeom.innerRings.count() > 0) {
+ for (var k = 0; k < currentGeom.innerRings.count(); k++) {
+ var currentRing = currentGeom.innerRings.get(k);
+ var previousPoint = realToMap(mapframe, currentRing.get(0));
+ for (var j=1, jlen = currentRing.count(); j < jlen; j++) {
+ (function () {
+ var currentPoint = realToMap(mapframe, currentRing.get(j));
+
+ var pq = calculateVisibleDash(previousPoint, currentPoint, mapframeWidth, mapframeHeight);
+ if (pq) {
+ drawLine([pq[0].x-1, pq[1].x-1], [pq[0].y-1, pq[1].y-1], col);
+ }
+ previousPoint = currentPoint;
+ })();
+ }
+
+ }
+ }
+ // paint line or outer ring
var previousPoint = realToMap(mapframe, currentGeom.get(0));
for (var j=1, jlen = currentGeom.count(); j < jlen; j++) {
(function () {
@@ -1468,7 +1724,16 @@
* @param {String} color a color
*/
this.del = function(m, color) {
- var a = gA.findMultiGeometry(m);
+ var newMultiGeom;
+ if (m.name == nameMultiGeometry) {
+ newMultiGeom = m;
+ }
+ else if (m.name == nameGeometry) {
+ var newMultiGeom = new MultiGeometry(m.geomType);
+ newMultiGeom.add(m);
+ }
+
+ var a = gA.findMultiGeometry(newMultiGeom);
var del = false;
for (var i=0; i<a.length && del === false; i++) {
if (gA.get(a[i]).color == color) {
@@ -1485,7 +1750,15 @@
* @param {String} color the color of the highlight
*/
this.add = function(m, color) {
- gA.addCopy(m);
+
+ if (m.name == nameMultiGeometry) {
+ gA.addCopy(m);
+ }
+ else if (m.name == nameGeometry) {
+ var newMultiGeom = new MultiGeometry(m.geomType);
+ newMultiGeom.add(m);
+ gA.addCopy(newMultiGeom);
+ }
if (typeof(color) != 'undefined') {gA.get(-1).color = color;}
else {gA.get(-1).color = lineColor;}
};
@@ -1717,6 +1990,19 @@
if (geom.name == nameGeometryArray || geom.name == nameMultiGeometry){
for (var j = 0 ; j < geom.get(i).count() ; j++){
if (geom.get(i).name == nameMultiGeometry){
+ // inner rings
+ if (geom.get(i).get(j).geomType == geomType.polygon && geom.get(i).get(j).innerRings && geom.get(i).get(j).innerRings.count() > 0) {
+ for (var l = 0; l < geom.get(i).get(j).innerRings.count(); l++) {
+ var currentRing = geom.get(i).get(j).innerRings.get(l);
+ for (var k = 0 ; k < currentRing.count() ; k++){
+ if ((currentRing.isComplete() === true && typeof(point) == 'undefined') || (typeof(point) != 'undefined' && !currentRing.get(k).equals(point))){
+ this.add(currentRing.get(k));
+ }
+ }
+
+ }
+ }
+ // lines, points, outer rings
for (var k = 0 ; k < geom.get(i).get(j).count() ; k++){
if ((geom.get(i).get(j).isComplete() === true && typeof(point) == 'undefined') || (typeof(point) != 'undefined' && !geom.get(i).get(j).get(k).equals(point))){
this.add(geom.getPoint(i, j, k));
More information about the Mapbender_commits
mailing list