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

how to reduce polygon to fit current zoom level resolution

Mission: create polygon of 1000 verticles and display it w\o lags

Goal: control LOD in real time

Step1. Create Polygon

lets create circle



    //lests create circle

    var polydata=[];

    var Nverts  =1000;

    var step    =Math.PI*2/Nverts;

    var radius  =0.03;

    var i;

    for(i=0;i<Nverts;i++){

      

      polydata.push(new GLatLng(37.4419  +radius*Math.cos(i*step),

                                -122.1419+radius*Math.sin(i*step)));

    }

    

next add it to map



    return new smartPolygon(createCircle(),map,new CoordinatesMapper(map));

    

setup redraw on zoom change



    GEvent.addListener(map, "zoomend", function(){

        _this.render();

    });

    

and change complexity on zoom change



    //convert data to screen space

    var set=this.mapper.toScreenSpace(this.data);

    var inL=set.length;

    //reduce

    set=this.performReduce(set);

    var outL=set.length;

    /** log **/

    document.getElementById("message").innerHTML='polygon reduced from '+inL+' to '+outL;

    //convert back to map space and return

    return this.mapper.toMapSpace(set);

    

But how to change it?


having points 1,2,3 and 4 we need to remove point 2 but keep point 3.

Lets create vector from 1 to 3, and from 1 to 4. We need to caclucate perpendicular P from 3 to L

If it is greater that some delta - so we have visible shift. And we store point 1 and 3 in result set.




    var resultset=[];

    var L=dataset.length;

    resultset.push(dataset[0]);

    dataset.push(dataset[L-1]);    

    var cur=0;

    var j=0;

    for(j=1;j<L;j++)

    {

        var x1=dataset[cur].x;

        var y1=dataset[cur].y;



        var x2=dataset[j  ].x;

        var y2=dataset[j  ].y;



        var x3=dataset[j+1].x;

        var y3=dataset[j+1].y;

        //first points must be different in screen space 

        if(!(((Math.round(x1)==Math.round(x2)) && (Math.round(y1)==Math.round(y2))) ||

             ((Math.round(x2)==Math.round(x3)) && (Math.round(y2)==Math.round(y3)))))

        {



            /*

             goal - create two vectors -

             from current to test point

             and from current to next point

             we need to drop a perpendicular from test point to cur-last vector

             just simple mathematics

            */

            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 v2=this._norm(vx2,vy2);



            var dot=this._dot(v1,v2);

            var sa=Math.sin(Math.acos(dot));



            var perp=sa*len;

            //so if perpendicular is bigger than delta, and length of vector is bigger than delta

            //add point to result set

            if(Math.abs(perp)>=delta && len>=delta)

            {

                cur=j;

                resultset.push(dataset[j]);



            }

        }

    }

    

Next iteration will begin from point 3.

In any case - it works!

and, all of this you can see online


Just zoomin and out, and set different deltas(end press enter) to see how it works!

Homework: inherit smartPolygon from GOverlay to produce more transparent 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

How to reduce polygon complexy and be happy

No comments:

Post a Comment