google earth load the KML file failed - kml

I have exported the KML file(ICBC.kml)of the 3D model from google earth, and I want to load the 3D model to the google earth plugin, but I can't get the result, many thanks for your suggestion.
javascript code for loading the kml
// Create the placemark.
var placemark = ge.createPlacemark('');
// Get the current view`enter code here`
var myCamera = ge.getView().copyAsCamera(ge.ALTITUDE_RELATIVE_TO_GROUND);
// Set new latitude and longitude values
myCamera.setLatitude(30.55552076525944);
myCamera.setLongitude(114.3344795151639);
myCamera.setAltitude(500);
// Placemark/Model/Location
var loc = ge.createLocation('');
loc.setLatitude(myCamera.getLatitude());
loc.setLongitude(myCamera.getLongitude());
// Update the view in Google Earth
ge.getView().setAbstractView(myCamera);
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.OpenTextFile("http://localhost/ICBC.kml",1,true);
var kmlobject = ge.parseKml(f.ReadAll());
ge.getFeatures().appendChild(kmlobject);
var la = ge.createLookAt('');
la.set(30.55552076525944, 114.3344795151639, 500, ge.ALTITUDE_RELATIVE_TO_GROUND, 0, 45, 900);
ge.getView().setAbstractView(la);

If you have the KML file, you shouldn't use parseKml, it's a better practice to use fetchKml, that doesn't need the string of the Kml to be passed, just the URL of the KML.
In your case you should use this line:
var href = UrlOfKML;
google.earth.fetchKml(googleEarthInstance, href, function(kmlObject) {
if (kmlObject)
ge.getFeatures().appendChild(kmlObject);
});
If you have more doubts about the differences of fetchKml and parseKml check this link: Importing KML - GE docs

Related

Google Maps - KML Layer Not Appearing on Map

I'm having an issue where my KML Layer does not appear on an embedded google map on my website.
I made a free website using google sites and uploaded my KML file to it so that I could set the url: 'https://sites.google.com/site/kmlroute/home/kml'. The google map itself shows up but the KML layer at that url does not.
My code is below. Does anyone see any syntax errors, logic errors, or anything of the sort that would be stopping my KML Layer from appear on my map???
Any comments, help, and advice is welcome and sincerely appreciated.
function initMap(lat, lng) {
var myLatLng = {lat: lat, lng: lng};
// Create a map object and specify the DOM element for display.
var map = new google.maps.Map(document.getElementById('bus_1_map'), {
center: myLatLng,
scrollwheel: false,
zoom: 12
});
var route = new google.maps.KmlLayer({
url: 'https://sites.google.com/site/kmlroute/home/kml',
map: map
});
You need to pass the URL of the XML file itself.
Try this:
var route = new google.maps.KmlLayer({
url: 'https://sites.google.com/site/kmlroute/home/kml/Bus%2022%20Route.kml.xml?attredirects=0&d=1',
map: map
});
How did I the url?
Go to https://sites.google.com/site/kmlroute/home/kml
Copy link address of the download arrow.

How to use Maki svg icons with Snap.svg?

I'm experimenting with Snap in order to use svg and need to be able to use the Maki icons defined in https://github.com/mapbox/maki.
My plan is to load the svg's I need, and then instantiate them for particular icons on a piece of Snap paper. But in order for this to work, I need to place the icon at a particular place on the paper, but I can't get translation to work. Neither one of the translation techniques below works; the code works as is, but always places the icon at the top left.
What am I missing? There's not enough documentation on Snap, and I don't know if the problem is with the way the Maki icon svg is defined, or my use of Snap.
var icon = Snap.load("maki/bicycle-24.svg", function(f) {
var g = f.select("g").clone();
// var g = f.select("#layer1").clone(); // also works
// g.transform("t120,120");
// var t = new Snap.Matrix();
// t.translate(120,120);
// g.transform(t);
paper.append(g);
});
The cloning needs to happen after the append, as when loading an svg in Snap its just a fragment.
So you will need to do something like...
paper.append(f);
var element = paper.select('#someId').clone();
element.transform( myTransform );
Thank you! That did the trick! And since Snap is so poorly documented, I'm going to insert the code here that allows a general solution.
// Base set from which markers are constructed
var iconSet = paper.group();
iconSet.attr({ class: 'hide' });
// Instantiations of icons
var markers = paper.g();
// Now, create SVG shape
var icon = Snap.load("maki/bicycle-24.svg", function(icon) {
// Add it to the icon set
iconSet.append(icon);
// Instantiate it and remove from main view
var element = paper.select('#svg4460'); // Copies it!
// var element = paper.select('#base'); // Selects something but doesn't work
// var element = paper.select('#layer1'); // Selects something but doesn't work
// var element = paper.select('#bicycle-24'); // Silent fail
element = element.clone();
element.remove();
// Clone this icon and move it
var t = new Snap.Matrix();
t.translate(10,120);
element.transform(t);
// Insert into main document view (markers)
markers.add(element);
});

Highlighting or Bolding the Borders of a kml Polygon

Hey after loading a kml file to google earth I was trying to have when a user clicks a certain polygon from the kml, to have that polygon highlighted.
So far I can record the click event, get the event type (KmlPlacemark) and grab its kml markup.
I tried doing something similar to this example where they add a placemark to the getFeatures of the kmlObject but both target and type don't seem to have 'getFeatures'. After looking around the documentation I think I might either want setOutline from Kml Polystyle class or setWidth() from KmlLineStyle class but am not sure. Also when I try something like target.setOutline(true); it doesn't work.
Can anyone tell me if I'm on the right track, hints to what I'm doing wrong, and if there's a better way to do this?
function recordEvent(event) {
var target = event.getTarget();
var type = target.getType();
if(type == "KmlPolygon") {
alert("KMLPolygon ");
}else if(type == "KmlPlacemark") {
// // get the data you want from the target.
var description = target.getDescription();
var balloon = target.getBalloonHtml();
var outputKml = target.getKml();
if ('getFeatures' in event) {
console.log("test");
event.getFeatures().appendChild(placemark);
}
console.log("hello?")
// target.setOutline(true);
console.log(outputKml);
}
};
google.earth.addEventListener(ge.getGlobe(), 'click', recordEvent);
Thanks!
I find the best way to do what you are asking is to:
Detect click events like you currently do
If clicked, create a new Style, then assign it to the target
var newStyle = ge.createStyle('');
// Assign your Style's attributes such as LabelStyle and IconStyle
// eg to set the scale of your label
newStyle.getLabelStyle().setScale(2.5);
// Set the Style
target.setStyleSelector(newStyle);
Edit to add in this link of a Google example showing it more in depth
https://code.google.com/apis/ajax/playground/#styling_placemarks_using_style_maps

JavaScript global variable to store kml model object

I'm developing a webpage to display google earth and a kml object. There will be two frames, one is the earth + kml object, the other is to display kml object's info like altitude, latitude, longitude...
I'm done with load the kml object and display its info on the page. Now, I want to add some events to control the kml object with keyboard, to move it and reflect all the changes in coordination onto the display frame.
In order to do that, I create my own object:
//Constructor for object ModelInfo
function ModelInfo(name) {
var me = this;
me.model = null;
me.name = name;
me.lon = 120.89250214028388;
me.lat = 22.17480037801846;
me.alt = 15.00;
me.heading = 0.0;
me.tilt = 0.0;
me.roll = 0.0;
me.kmlUrl = "";
me.ALTITUDE_MODE = ge.ALTITUDE_RELATIVE_TO_GROUND;
me.scaleX = 0.3;
me.scaleY = 0.3;
me.scaleZ = 0.3;
}
When I fetchKml, I store the kml model into my objectInfo.model:
// Fetch a KML file and show it
function finished(object, objInfo) {
if (!object) {
// wrap alerts in API callbacks and event handlers
// in a setTimeout to prevent deadlock in some browsers
setTimeout(function() {
alert('Bad or null KML.');
}, 0);
return;
}
var modelPlacemark;
walkKmlDom(object, function() {
if (this.getType() == 'KmlPlacemark' && this.getGeometry()
&& this.getGeometry().getType() == 'KmlModel') {
modelPlacemark = this;
}
});
var model = modelPlacemark.getGeometry();
objInfo.model = model;
This is how I call fetchKml
shutter = new ModelInfo("Shutter"); //shutter is global variable
shutter.kmlUrl = 'http://120.125.80.113/kml/student/space_shuttle_23_20110812a/space_shuttle_23_20110812a_SP.kmz';
google.earth.fetchKml(ge, shutter.kmlUrl, function(obj) {
finished(obj, shutter);
});
But the problem is, after fetchKml finishes, I try to access shutter.model, it is always null, but when I access shutter.model from within function finished, it is not null
So my question is how did it happen? Is there anyway to store kml object in a global variable to modify its attribute later?
Thanks,
Hans
After several hrs trying to figure out why, I decided to use Firebug to debug the code and found out the reason. I still don't know why though.
The name I used for my variable "shutter" somehow isn't listed as a member of this page when I debugged using Firebug. When I changed it to flying_obj then everything is ok, I was able to store the kml object inside my flying_obj.model
Anyone knows what's wrong with the name "shutter" please explain it to me. It'd be great!!
Hans

How do I optimize the loading time of Google Earth Web Plugin if I have a very large KML file?

My client has a very large KML file, it contains around 6000+ placemarks and these placemarks have to appear as 3D models on the map. What's even worse is that the KML file does not contain that <link> tag for the COLLADA file, which means I have to traverse the KML file and attach a COLLADA file before it can be displayed on google earth. Now I can already traverse and add a 3D model for each placemark. I tested it with a very small KML file(which contains like less than 100 placemarks) and it worked great as expected...but when I used the very large KML file which had like 6000+ placemarks on it, the plugin just crashes and I am advised to refresh the browser, only to find it crashing again... :(
Any advice on this?
Is there a limit to the number of placemarks I can put on google earth web plugin?
How do I make the loading faster?
function render3DPoles(polesKmlLink){
google.earth.fetchKml(ge,polesKmlLink, function(object){
if(object){
var item = object.getFeatures().getChildNodes().item(0);
var folder = item.getFeatures().getChildNodes();
var latitude;
var longitude;
for(var i = 0; i<folder.getLength(); i++){
var placemark = folder.item(i);
latitude = placemark.getGeometry().getLatitude();
longitude = placemark.getGeometry().getLongitude();
var model = ge.createModel('');
var location = ge.createLocation('');
model.setLocation(location);
var link = ge.createLink('');
link.setHref('insert URL of collada file here');
model.setLink(link);
location.setLatitude(latitude);
location.setLongitude(longitude);
model.setLocation(location);
placemark.setGeometry(model);
ge.getFeatures().appendChild(placemark);
}
var la = ge.createLookAt('');
la.set(latitude,longitude, 25, ge.ALTITUDE_RELATIVE_TO_GROUND,180, 60, 100);
ge.getView().setAbstractView(la);
} else {
setTimeout(function() {
alert('Bad or null KML.');
},0);
}
});
}
I have dealt with dealing 10,000s of placemarks and other kml objects in the earth plugin and the best way I find is manage the data in a javascript object. dealing with them in standard kml would often crash things.
parse the kml before hand into something that you can handle as an object
start with:
var myModels = {};
for adding the first item if the id is 'foo' or a numeric do something like:
myModels['foo'] = {
description: 'some description for foo',
longitude: 100.12345,
latitude: 45.4567
linkUrl: 'http://mydomain.com/mymodels/foo.dae',
kmlObject: null};
now looking at the code from:
http://code.google.com/apis/ajax/playground/?exp=earth#creating_3d_models
you will have something similar to:
var placemark = ge.createPlacemark('');
placemark.setName('model');
var model = ge.createModel('');
.......
placemark.setGeometry(model);
now go:
myModals['foo'].kmlObject = placemark;
this will give you a quick reference to the model if you need to change it or remove it with just
myModels['foo'].kmlObject
no need to traverse the tree again.
one thing I found to be faster was to define kml client side and use parseKml to load it rather then create individual objects and add them.
also you can build in logic to only add the dae model that are within the area the user is looking at
to loop through all the items
var i, iModel;
for (i in myModels){
iModel = myModels[i];
if(myModels[m].kmlObject == null){
'add if statement to check if the models long/lats are in current view with
' iModel.longitude, iModel.latitude
}
}
also rather than add everything in one operation, add 10-20 model in a single batch and use setTimeout to start another batch operation a second later and leverage .executeBatch
https://developers.google.com/earth/documentation/reference/google_earth_namespace#ab26414915202d39cad12bcd5bd99e739
While there's no technical limit, the more you add the more resources get used. Depending on the complexity of your models and other data, you will be able to add more or less, but 6000 is quite a lot of to display at once even for simple markers.
One solution for a large/complex KML is to create regionated KMLs instead, such that you are loading just the data you need at any given time, based on visible regions (see http://code.google.com/apis/kml/documentation/regions.html )

Resources