سؤال

I am building a c# application that uses the Google Earth plugin through a web browser control. As part of the application, I need to be able to create a multi-select box around a certain area on the globe (think something similar to drag-selecting multiple files in your file browser).

The way I have it set up right now, the c# code keeps track of when I am in select mode, if I am, the first left click pulls the lat-long of that point from the google earth plugin. After that, mouse moves get the lat-long of the opposite corner, and then the c# code calls the following 2 javascript functions:

function clearHighlightBox(){
    var placemark = ge.getElementById('DARTselectBox');
    if(placemark)
    {
        ge.getFeatures().removeChild(placemark);
    }
}

function setHighlightBox(lat1, long1, lat2, long2){
    clearHighlightBox();
    var placemark = ge.createPlacemark('DARTselectBox');
    var lineString = ge.createLineString('');
    var coords = lineString.getCoordinates();
    coords.pushLatLngAlt(lat1, long1, 5000);
    coords.pushLatLngAlt(lat1, long2, 5000);
    coords.pushLatLngAlt(lat2, long2, 5000);
    coords.pushLatLngAlt(lat2, long1, 5000);
    coords.pushLatLngAlt(lat1, long1, 5000);
    placemark.setGeometry(lineString);
    ge.getFeatures().appendChild(placemark);
}

First off, creating the ID for the placemark this way does not seem to work (ge.createPlacemark('DARTselectBox');). If I switch this to clear everything and remove the ID from the create Placemark call, this at least doesn't crash. However, even when I do that, I only see the right vertical leg of my rectangle.

هل كانت مفيدة؟

المحلول

If I switch this to clear everything and remove the ID from the create Placemark call, this at least doesn't crash.

The issue is that you can't remove then add an object with the same ID that quickly. In simple terms it is the call to ge.createPlacemark('DARTselectBox') that is causing the crash because the ID DARTselectBox is still being used internally. You can eventually use it again, but the time is dependent on the WebBrowser control's garbage collection.

To avoid the crash you could try calling release on the placemark so that the ID is freed immediately. See this note on what calling release does (My emphasis)

Permanently deletes an object, allowing its ID to be reused. Attempting to access the object once it is released will result in an error.

Failing that you could simply toggle the visible state of the placemark, rather than adding and removing it each time.

The actual issue with the ID reuse is listed as a bug and there is some more information on the problem here

Edit:

Looking at it looks like there could be a bug with the release method.

If you read the link I posted code.google.com/p/earth-api-samples/issues/detail?id=253 some of the comments at the bottom seem to suggest this.

Anyhow, a hash would work, so would an incremental counter. But I don't understand why you don't simply set the visibility to false, or else create a Placemark without an ID at all and simply keep a reference to it during the operation.

The display issue is possibly due to tessellation and altitude mode.

Try calling setTessellate(true) on the Placemarks geometry object and also make sure the altitude mode is set to clampToGround - to do this you call setAltitudeMode(ge.ALTITUDE_CLAMP_TO_GROUND) - again on the Placemarks geometry object.

So you have

var lineString = ge.createLineString('');
lineString.getCoordinates().pushLatLngAlt( ... );
lineString.setTessellate(true);
lineString.setAltitudeMode(ge.ALTITUDE_CLAMP_TO_GROUND);

If that doesn't work, can you try turning the terrain layer off and checking if the lines are there or not?

Also, I have written a free control library that does lots with the API - it is GPL so you can use it pretty much however you like. It does cover lots of things like this. http://code.google.com/p/winforms-geplugin-control-library/

نصائح أخرى

I have an application that does something very similar. Unfortunately the code is not GPL, so I can't release it here. In general, your approach is correct, but I believe your problem is the structure you are using for building your box.

You either need to use four separate KmlLineString objects (one for eatch edge of the box) or a KmlLinearRing to create an enclosed box. I don't believe the KmlLineString was designed to create a closed polygon, that's what the linear ring is for.

The way you compute your box points looks good to me (comparing it against my working solution), so I'm thinking if you just swap createLineString for createLinearRing you'll be well on your way.

Google's samples are at the link below. You'll see they use linearRing for the enclosed polygon. (About halfway down the page)

https://developers.google.com/earth/documentation/geometries

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top