Dont afraid maps. Google maps v3, v2, ovi, yandex maps. Maps is your friend. Try them, love them. I`ll show how to cook them

Tuesday, March 16, 2010

Basic polygon editor

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

No comments:

Post a Comment