Mission:Make interface able to edit polygon
Goal:Create polygon with edit interface
Step1. Create Polygon
Lets define polygon of 3 points
var verticles=[new GLatLng(37.4419 , -122.1419),
new GLatLng(37.4419+0.03, -122.1419),
new GLatLng(37.4419 , -122.1419+0.03)]
myPoly = new myEditablePolygon(verticles,map);
myPoly.attachClickEvent();
myPoly.draw();
What next?Next - we need to edit it. Drag edge markers, create new, and delete unused
And i`ll present THREE variants of editor. In one box :)
bla-bla-bla.. lets go down to mathematics
Step2. Determine where we click, and place to add new point
Algorithm is the same as in article about polygon reduceTake the point, find distance from it to all segments of polygon and add new verticle in right place!
So tranform it to screen space
/* transform polygon and click point to screen space */
var screen=this.mapper.toScreenSpace(set);
var point =this.mapper.toScreenSpace([pt])[0];
//and add first point as last point
var L=set.length;
screen.push(screen[0]);
And find that point!
var minval=10000000;
var minfit=-1;
var x2=point.x;
var y2=point.y;
var i;
for( i=0;i<L;i++){
//remeber the milk!
/** same login. find distance from point to segment */
var x1=screen[i].x;
var y1=screen[i].y;
var x3=screen[i+1].x;
var y3=screen[i+1].y;
var vx1=x2-x1;
var vy1=y2-y1;
var len=Math.sqrt(vy1*vy1+vx1*vx1);
var v1=this._norm(vx1,vy1,len);
var vx2=x3-x1;
var vy2=y3-y1;
var len2=Math.sqrt(vy2*vy2+vx2*vx2);
//if distance to test point is greater that distance to other side of the egde - skip
if(len>len2){
continue;
}
var v2=this._norm(vx2,vy2);
var dot=this._dot(v1,v2);
var angle=(Math.acos(dot));
/** we need positive angle and not greater that 60 degress*/
if(angle>Math.PI/3)continue;
var sa=Math.sin(angle);
var perp=sa*len;
// so this is best fit for point
if(perp<minval){
minval=perp;
minfit=i;
}
}
//and distance must be not very big
if(minval<50){
return minfit;
}
return -1;
Done, all other work you can see by yourself in scriptsStep3. Delete Verticle
just click the marker :)Google polygon editor variant 1
online version, you can drag markers and you mustCLICK the map near edge to spawn new verticle
GEvent.addListener(this.map, "click", function(overlay,point){
_this.newMarker(point,'auto');
});
Google polygon editor variant 2
online version, you can drag markers and just move mouse over edge to create new verticle.if you click spawned marker - it become normal. So variant like one you can see on wikimapia.org
GEvent.addListener(this.map, "mousemove", function(point){
if(!point)return;
//get current point and move it by 30 pixel to bottom
var sx=_this.mapper.toScreenSpace([point])[0];
sx.y+=30;
point=_this.mapper.toMapSpace([sx])[0]
//remove old marker
if(_this.dragMarker){
_this.removeHold(_this.dragMarker.holdpoint);
_this.map.removeOverlay(_this.dragMarker);
delete _this.dragMarker;
}
//find where we can(if we can) place new marker
var position=_this.findBestPosition(point);
if(position<-1)return;
else{
//and place it!
var marker=_this.newMarker(point,'auto');
_this.dragMarker=marker;
}
});
Google polygon editor variant 3
online version, you can drag markers and.. hm who add green markers where?How i do it? Just perform some preprocess before render
myEditablePolygon.prototype.preprocess = function(){
this.removeGhosts();
this.ghostMarkers=[];
var i=0;
var verts=[];
var inverts=this.verticles.slice(0);
var L=inverts.length;
inverts.push(inverts[0]);
// lets to trought verticles and create some markers in middle of edges
for ( i=0;i<L;i++){
var _this=this;
(function(){
var x1=inverts[i]._x;
var y1=inverts[i]._y;
var x2=inverts[i+1]._x;
var y2=inverts[i+1]._y;
var point = new GLatLng(x1+(x2-x1)/2,y1+(y2-y1)/2);
//blue marker from google`s exmaple
var blueIcon = new GIcon(G_DEFAULT_ICON);
blueIcon.image = "http://gmaps-samples.googlecode.com/svn/trunk/markers/blue/blank.png";
var marker = new GMarker(point, {draggable: true,icon:blueIcon});
marker.parent=_this;
_this.ghostMarkers.push(marker);
_this.map.addOverlay(marker);
//on mouse down - remove blue marker and create new normal marker
GEvent.addListener(marker, "mousedown", function() {
this.parent.map.removeOverlay(this);
this.parent.newMarker(this.getPoint(),'auto')
});
})();
}
return this.verticles;
}
Homework: inherit from smartPolygon to perform more complex solution
All of sections, i list here, is allready done by me. I need just to wrap code into article, and, yap, english article :)
If you want to know more - ask
If you want to know more - ask
No comments:
Post a Comment