开发者

Google Earth API Moving a polygon

I just starting coding with Google Earth using the GEPlugin control for .Net and still got a lot to learn.

What has got me puzzled is when I try to drag a polygon.

The method below is called whenever the mousemove event fires and should be moving each point of the polygon while retaining the orginal shape of the polygon. The lat / long for each point is changed but the polygon does not move position on the map.

Will moving a point in a polygon cause开发者_开发问答 it to redraw, do I need to call a method to force a redraw or perhaps do something else entirely?

Thanks!

private void DoMouseMove(IKmlMouseEvent mouseEvent)
    {
        if (isDragging)
        {
            mouseEvent.preventDefault();

            var placemark = mouseEvent.getTarget() as IKmlPlacemark;

            if (placemark == null)
            {
                return;
            }

            IKmlPolygon polygon = placemark.getGeometry() as IKmlPolygon;


            if (polygon != null)
            {
                float latOffset = startLatLong.Latitude - mouseEvent.getLatitude();
                float longOffset = startLatLong.Longitude - mouseEvent.getLongitude();

                KmlLinearRingCoClass outer = polygon.getOuterBoundary();
                KmlCoordArrayCoClass coordsArray = outer.getCoordinates();

                for(int i = 0; i < coordsArray.getLength(); i++)
                {
                    KmlCoordCoClass currentPoint = coordsArray.get(i);
                    currentPoint.setLatLngAlt(currentPoint.getLatitude() + latOffset, 
                        currentPoint.getLongitude() + longOffset, 0);
                }
            }
        }
    }


Consider voting for these issues to be resolved

  • http://code.google.com/p/earth-api-utility-library/issues/detail?id=33
  • http://code.google.com/p/earth-api-samples/issues/detail?id=167

You may find some hints at the following link:

http://earth-api-utility-library.googlecode.com/svn/trunk/extensions/examples/ruler.html


UPDATE:

I've released the extension library: https://bitbucket.org/mutopia/earth

See https://bitbucket.org/mutopia/earth/src/master/sample/index.html to run it.

See the drag() method in the sample code class, which calls setDragMode() and addDragEvent() to enable dragging of the KmlPolygon.


I successfully implemented this using takeOverCamera in the earth-api-utility-library and three events:

setDragMode: function (mode) {
    // summary:
    //      Sets dragging mode on and off
    if (mode == this.dragMode) {
        Log.info('Drag mode is already', mode);
    } else {
        this.dragMode = mode;
        Log.info('Drag mode set', mode);
        if (mode) {
            this.addEvent(this.ge.getGlobe(), 'mousemove', this.dragMouseMoveCallback);
            this.addEvent(this.ge.getGlobe(), 'mouseup', this.dragMouseUpCallback);
            this.addEvent(this.ge.getView(), 'viewchange', this.dragViewChange, false);
        } else {
            this.removeEvent(this.ge.getGlobe(), 'mousemove', this.dragMouseMoveCallback);
            this.removeEvent(this.ge.getGlobe(), 'mouseup', this.dragMouseUpCallback);
            this.removeEvent(this.ge.getView(), 'viewchange', this.dragViewChange, false);
        }
    }
},

This is in a utility library within a much larger project. dragMode is a boolean which adds and removes events. These three events control what happens when you drag. addEvent and removeEvent are my own wrapper functions:

addEvent: function (targetObject, eventID, listenerCallback, capture) {
    // summary:
    //      Convenience method for google.earth.addEventListener
    capture = setDefault(capture, true);
    google.earth.addEventListener(targetObject, eventID, listenerCallback, capture);
},

removeEvent: function (targetObject, eventID, listenerCallback, capture) {
    // summary:
    //      Convenience method for google.earth.removeEventListener
    capture = setDefault(capture, true);
    google.earth.removeEventListener(targetObject, eventID, listenerCallback, capture);
},

Ignoring the minor details, all the important stuff is in the callbacks to those events. The mousedown event locks the camera and sets the polygon I'm dragging as the dragObject (it's just a variable I'm using). It saves the original lat long coordinates.

this.dragMouseDownCallback = lang.hitch(this, function (event) {
    var obj = event.getTarget();
    this.lockCamera(true);
    this.setSelected(obj);
    this.dragObject = obj;
    this.dragLatOrigin = this.dragLatLast = event.getLatitude();
    this.dragLngOrigin = this.dragLngLast = event.getLongitude();
}

The mousemove callback updates to the latest lat long coordinates:

this.dragMouseMoveCallback = lang.hitch(this, function (event) {
    if (this.dragObject) {
        var lat = event.getLatitude();
        var lng = event.getLongitude();
        var latDiff = lat - this.dragLatLast;
        var lngDiff = lng - this.dragLngLast;
        if (Math.abs(latDiff) > this.dragSensitivity || Math.abs(lngDiff > this.dragSensitivity)) {
            this.addPolyCoords(this.dragObject, [latDiff, lngDiff]);
            this.dragLatLast = lat;
            this.dragLngLast = lng;
        }
    }
});

Here I'm using some fancy sensitivity values to prevent updating this too often. Finally, addPolyCoords is also my own function which adds lat long values to the existing coordinates of the polygon - effectively moving it across the globe. I do this with the built in setLatitude() and setLongitude() functions for each coordinate. You can get the coordinates like so, where polygon is a KmlPolyon object:

polygon.getGeometry().getOuterBoundary().getCoordinates()

And of course, the mousedown callback turns off the drag mode so that moving the mouse doesn't continue to drag the polygon:

this.dragMouseUpCallback = lang.hitch(this, function (event) {
    if (this.dragObject) {
        Log.info('Stop drag', this.dragObject.getType());
        setTimeout(lang.hitch(this, function () {
            this.lockCamera(false);
            this.setSelected(null);
        }), 100);
        this._dragEvent(event);
        this.dragObject = this.dragLatOrigin = this.dragLngOrigin = this.dragLatLast = this.dragLngLast = null;
    }
});

And finally, _dragEvent is called to ensure that the final coordinates are the actual coordinates the mouse event finished with (and not the latest mousemove call):

_dragEvent: function (event) {
    // summary:
    //      Helper function for moving drag object
    var latDiff = event.getLatitude() - this.dragLatLast;
    var lngDiff = event.getLongitude() - this.dragLngLast;
    if (!(latDiff == 0 && lngDiff == 0)) {
        this.addPolyCoords(this.dragObject, [latDiff, lngDiff]);
        Log.info('Moved ' + latDiff + ', ' + lngDiff);
    }
},

The mousemove callback isn't too important and can actually be ignored - the only reason I use it is to show the polygon moving as the user moves their mouse. Removing it will result in the object being moved when they lift their mouse up.

Hopefully this incredibly long answer gives you some insights into how to implement dragging in the Google Earth API. And I also plan to release my library in the future when I've ironed out the kinks :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜