О немО себе[code]/maps/Мои СоседиМой ЗимаШопМоя СтройкаЗверь Дверь

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 reduce
Take 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 scripts

Step3. Delete Verticle

just click the marker :)

Google polygon editor variant 1

online version, you can drag markers and you must CLICK 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

lest make a Very simple polygon editor

Кащей увидел избушку на курьих ножках и говорит:
*Избушка, повернись к лесу задом, ко мне передом!*
Избушка повернулась, Кащей сделал свое дело и говорит:
*ХОРОШО ИМЕТЬ ДОМИК В ДЕРЕВНЕ!*