How do I calculate mxgraph pixel co-ordinates from

2019-08-21 13:03发布

问题:

The mxgraph Google Maps example (and demo) shows a simple implementation that create a Google Map overlay.

However I cannot figure out the correlation between the vertex pixel co-ordinates and the equivalent lat/long co-ordinates.

Line 140 of the example shows some hard-coded pixel co-ordinates (23,23) for Seattle:

var n1 = graph.insertVertex(parent, null, {label:'Seattle'}, 23, 23, 10, 10);

I want to display a geographic data set (i.e. I have latitude/longitude) but I can not figure out the conversion to mxGraph vertex pixel co-ordinates.

The Google API's "fromLatLngToDivPixel" does not work (it returns the lat/long of the centre of the map as 0,0), neither does "fromLatLngToContainerPixel".

Even weirder, a vertex with co-ordinates of 0,0 does not appear in the top left corner of the map (it is a little inside the map).

回答1:

So it's a little complicated.

I finally created two classes to help out:

// Represent a map pixel
class PixelPos {
    constructor(x,y) {
        this._x = x;
        this._y = y;
    }

    get x(){
        return this._x;
    }
    get y(){
        return this._y;
    }
}

// Handles converting between lat/log and pixels
// Based on the initial created map div container.
class CoordTranslator {

    constructor(graph, projection, bounds) {
        this._graph = graph;
        this._projection = projection;
        this._bounds = bounds;

        //
        var swb = this._bounds.getSouthWest();
        var neb = this._bounds.getNorthEast();

        this._neb_lat = neb.lat();
        this._swb_lng = swb.lng();

        this._map_width = neb.lng() - swb.lng();
        this._map_height = neb.lat() - swb.lat();

        // Get pixel values from the Geo boundary box
        var sw = this._projection.fromLatLngToDivPixel(swb);
        var ne = this._projection.fromLatLngToDivPixel(neb);

        //  Map pixel width and Height
        this._pix_width = (ne.x - sw.x);
        this._pix_height = (sw.y - ne.y);

        this._scale = graph.view.getScale();
    }

    // Convert the provided lat/long into a PixelPos    
    convert(lat, lng){
        var x = (lng-this._swb_lng)/this._map_width;
        x = x*this._pix_width;
        x = x/this._scale;

        var y = (this._neb_lat - lat)/this._map_height;
        y = y*this._pix_height;
        y = y/this._scale;

        // And, for some unknown reason, I have to magic a final offset!!
        return new PixelPos(x-5,y-3);
    }

}

I initialise the CoordTranslator class in the mxGraphOverlay.prototype.draw:

mxGraphOverlay.prototype.draw = function()
{

   if (drawn = 0){
     drawn = 1;
     ....
     let ct = new CoordTranslator(this.graph_, overlayProjection, this.bounds_);
     ....
     // 6193351 @ 46.8127123,14.5866472 
     var pp = ct.convert(46.8127123, 14.58664720);
     var n3 = graph.insertVertex(parent, null, {label:'6193351'}, pp.x, pp.y, 10, 10);
     ....
   }
}

There are probably better ways to initialise and use the CoordTranslator, but the ideas are here.