We want to display two KML files into the Google Earth plugin. KML 1 will have Folder 1, containing placemarks. KML 2, will have more placemarks that belong under Folder 1. Does KML/Google Earth support that? The reason for two KML’s is that we want to display KML 1 before we finish generating KML 2. Actually, we may have several KML files...
Yes there are a number of ways to do this.
One simple way would be to create Folder 1 via the api rather than via KML.
Then when you load your KML files you can simply append them to the folder you created
For example.
var folder = ge.createFolder("folder1");
google.earth.fetchKml(ge, "your.kml", function(kml) {
if(kml) {
folder.appendChild(kml);
}
});
If you did want or need to load Folder 1 via KML you could simply target it via getElementByUrl and then append any further KML to it.
var folder = ge.getElementByUrl("your.kml#folder1");
google.earth.fetchKml(ge, "more.kml", function(kml) {
if(kml) {
folder.appendChild(kml);
}
});
Finally, the KML NetworkLink and NetworkLinkControl elements could be used to link the files together - allowing you to update your data dynamically solely via KML...but without more information on your setup it is hard to offer any specific solutions in this regard.
Related
I am going to develop a mechanism to export as many as approx. 100 photos with their position information to a KML/KMZ file.
Just wondering what is the best practise to do this. My initial quick options are:
1. use html img tag in the description of a placemark to internally reference the actual photos wrapped in the internal "files" folder in the KMZ;
2. use html img tag in the description of a placemark to reference the URL of a photo (publicly accessible).
Option one involves writing all photos in the internal "files" folder of a KMZ. This would make it a massive file. Meanwhile, all photos would have to be loaded in memory during the loading of the KMZ file.
My question is with the option 2, if a particular photo would not be loaded until the user clicks on the placemark to open the popup balloon OR all the photos are loaded like the option 1?
Thanks!
Cheers,
Alex
You can think of Google Earth as a specialized web browser and the HTML within a given placemark as being handled same way HTML in a web browser is handled. In option 2 the images are not downloaded until user clicks the placemark and the description balloon is selected and starts to render.
Option 1 you have a huge KMZ file as you describe that must be downloaded entirely to the client and unpacked locally. The file may be too large to download in a mobile device if you want Google Earth mobile users to view it. The Google Earth essentially unpack the KMZ then access images as in the case of option 2 when the placemark with that image is selected. Only difference is that the entire collection must be downloaded in one shot so the initial startup time is slower and depends on network speed.
I have developed the following network link for dynamic updates :
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<NetworkLink>
<name>Loads TEST.kml</name>
<Link>
<href>/home/desktop/farhan/test.kml</href>
</Link>
</NetworkLink>
</kml>
Test.kml file has two placemarks.
My network link file is getting successfully updated on changes in Test.kml file
Now what I want to do is to place an 'IF' condition so that if a certain thing is true then placemark color is 'Green' Else 'Red'.
What should I do here ?? Is there any Java API I need to follow.
Depends how/where you want to host the KML and what those conditions are.
If the styles and conditions are static then you can generate the KML pre-set with those styles as part of the KML. For example, if you want to generate the KML based on some conditions such as population size > 100K => red, size > 50K => blue, otherwise white where each generated Placemark would have the appropriate shared share or inline style.
One popular Java-API to generate KML is the Java API for KML (or JAK for short).
If the views (based on conditions) are "dynamic" and user-selected then you have a couple of options:
Generate different versions/views of the Placemarks based on different conditions with NetworkLinks and radioFolders to load a particular view. The KML could be statically generated once or dynamically via a web-service, servlet, CGI-script, etc.
For example, the USGS has an earthquake real-time feed with multiple NetworkLinks each with a different view/color/size scheme for the same data (e.g. color by age vs magnitude).
Check out http://earthquake.usgs.gov/earthquakes/feed/earthquakes.kml
Use the Google Earth API to load, create, and modify KML in context of HTML and JavaScript with Google Earth running as a plugin in your web browser. This requires some JavaScript programming.
Use NetworkLinks as shown in your example combined with NetworkLinkControl elements to globally change the shared styles. See NetworkLinkControl tutorial. You can't add NetworkLinkControl elements to your KML directly in Google Earth so you have to author your KML manually or programmatically.
use php , if you are aware of it and generate kml with the help of your table and also you can use various plugins and JAK as told by jason above.
What you can do is :
connect your mysql db ( having latnlong ) through jdbc.
2 .Run a loop i.e while loop which will add placemarks as per the latitude and longitude and add other necessary element of kml like :
Element ristyle = doc.createElement("IconStyle"); // this will create an Icon.
make a new file through :
Result dest = new StreamResult(new File("file location"));
this will create your new kml file
-- place a condition here which will show your condition like a normal loop.
5 Make a network link and refer your kml file in this for manual updation.
I think this should work
Currently, I am loading a lot of placemarks on Google Earth on the website I created. Each placemark corresponds on a single file from the server. The placemarks are created one by one by the server coming from different images during initialization.
To ease the load of the server and the client, I am planning to change the implementation I mentioned using sprite image using css. Is this possible in Google Earth? I can't find any information about this. Maybe you can give some reference to do this.
Thank you very much.
Ability to use Image Sprites for Placemark Icons
I think you can do it something like:
ge.getFeatures().appendChild(me.placemark);
me.point = ge.createPoint('');
me.placemark.setStyleSelector(ge.createStyle(''));
var IconStyle = me.placemark.getStyleSelector().getIconStyle();
IconStyle.getColor().set(colour);
IconStyle.getHotSpot().setXUnits(ge.UNITS_FRACTION);
IconStyle.getHotSpot().setYUnits(ge.UNITS_FRACTION);
IconStyle.getHotSpot().setX(0.5);
IconStyle.getHotSpot().setY(0.5);
me.setLoc(lat,lon);
IMHO: if there are thousands of images in the sprite it will load it as many times as the number of placemarks on the map.
I have many large KML data-sets, which are served using a hierarchy of region-based network-links; as described in the KML reference:
Using Regions in conjunction with NetworkLinks, you can create a hierarchy of pointers, each of which points to a specific sub-Region. The <viewRefreshMode>, as shown in the following KML file, has an onRegion option, which specifies to load the Region data only when the Region is active. If you provide nested Regions with multiple levels of detail, larger amounts of data are loaded only when the user's viewpoint triggers the next load.
This works nicely when loaded in Google Earth.
I now wish to load these in an application using the Google Earth plug-in. And I need to access the loaded content via the Google Earth API; (i.e. attach click events, alter styles) to integrate the content into the application.
The issue is, I haven't found any reference to an 'on-load' event for network links. In my mind, the way this would work is:
Load top-level network link via the API, attaching a call-back function which will be invoked when the network-link is loaded.
In the call-back function, parse the KML returned by network link. For intermediate levels in the regionation hierarchy, this KML will contain only network links to the next regionation level. Load these into the plug-in via the API, again specifying the same call-back function, which will be invoked when these are loaded (i.e. when their region becomes visible).
Eventually, the KML returned will contain the actual 'content'. At this stage we load the actual content (i.e. placemarks) into the plug-in, after performing any desired modifications (e.g. attaching event-listeners, setting styles, etc).
I'm thinking the javascript would look something like the following.
Please note: this is just a rough sketch to perhaps aid in understanding my question. I am NOT asking why this code doesn't work.
//create network link
var networkLink = ge.createNetworkLink("");
networkLink.setName("Regionated hierarchy root");
// create a Link object
//the network-links contained in the kml that will be returned in this file
//are region-based; they will only be loaded when the user zooms into the relevant
//region.
var link = ge.createLink("");
link.setHref("http://foo.com/regionatedRoot.kml");
// attach the Link to the NetworkLink
networkLink.setLink(link);
//specify the callback function to be invoked when the network link is loaded
//this is is the part that doesn't actually exist; pure fiction...
networkLink.onLoad = networkLinkLoaded;
// add the NetworkLink feature to Earth
ge.getFeatures().appendChild(networkLink);
// function which will be invoked when a network-link is loaded
// i.e. when its region becomes active
function networkLinkLoaded(kml) {
//parse the kml returned for child network links,
//this will create the network link KmlObject, with a
//region specified on it.
for (childNetworkLink in parseNetworkLinks(kml)) {
//and append them, again hooking up the call-back
childNetworkLink.onLoad = networkLinkLoaded;
ge.getFeatures().appendChild(childNetworkLink);
}
//if the user has zoomed in far enough, then the kml returned will
//contain the actual content (i.e. placemarks).
//parse the kml returned for content (in this case placemarks)
for (placemark in parsePlacemarks(kml)) {
//here we would attach event-listeners to the placemark
ge.getFeatures().appendChild(placemark);
}
}
Is this possible?
Have I taken a wrong turn in my thinking? I believe I have followed recommended practices for managing large KML datasets, but I am unsure how to use these via the API.
Addendum:
As an example of the type of problem I am trying to solve:
Imagine you are building a web application using the Google Earth Plugin, and you want to display a placemark for every set of traffic-lights in the world. The placemarks should only display at an appropriate level-of-detail (e.g. when the camera is at 5km altitude). When a user clicks on a placemark, we want the web app to load statistics for that set of traffic-lights, and display them in a sidebar.
How would you engineer this?
You wouldn't need access to the object data directly to provide the functionality you require. You would handle the data load exactly like you have done, using a hierarchy of region-based network-links.
Then if your usage scenario is like the one you set out in your addendum then you would simply use the target data from the click event to load your statistical data based on the placemarks as required.
For example, you could simply set up a generic mousedown event handler on the window object and then test to see if the target is a placemark. You can add this generic listener before you load any data and it will still be fired when you click on your dynamically loaded placemarks. There is no need to attach individual event-listeners to the placemarks at all.
e.g.
window.google.earth.addEventListener(ge.getWindow(), 'mousedown', onWindowMouseDown);
var onWindowMouseDown = function(event) {
if (event.getTarget().getType() == 'KmlPlacemark') {
// get the placemark that was clicked
var placemark = event.getTarget();
// do something with it, or one of its relative objects...
var document = placemark.getOwnerDocument();
var parent = placemark.getParentNode();
// etc...
}
}
Not sure if this is quite what you want but there is a kmltree api that will:
build out the kml tree for you based on the kml given
allow you to have a 'kmlloaded' event handler
http://code.google.com/p/kmltree/
function initCB(instance){
ge = instance;
ge.getWindow().setVisibility(true);
var gex = gex = new GEarthExtensions(ge);
var tree = kmltree({
url: 'http://foo.com/regionatedRoot.kml',
gex: gex,
mapElement: $('#map3d'),
element: $('#tree'),
});
$(tree).bind('kmlLoaded', function(event, kmlObject){ //do something here });
tree.load();
}
it does require you to bring in another js api but it works pretty good and gives you some good built in functionality.
So far I haven't found anything just from the plug-in that will fire an event when the kml is loaded...
you might be able to try using fetchKml() especially if you are hardcoding that url for the link in there?
google.earth.fetchKml(ge, 'http://foo.com/regionatedRoot.kml', function(kmlObject){
//do logic here
});
We have a SharePoint Document library, where we store html files with links to external files. Samples:
mypicture.jpg.html
mywordfile.docx.html
mypdffile.pdf.html
and so on. Now by default all Files show up with the HTML Icon, referenced in the DOCICON.XML file. Thats of course correct as the .html extension shows, it is a HTML file. But we want the files to have different icons, based on their original file type.
Is there a way to automatically change the Icon
during rendering or
when we save the file to the library (via SharePoint API)?
Any other approachs?
Why not use a little jquery to change the icon during rendering? Each doc in your library should be contained in
<td class="ms-vb-icon"><a tabindex=...><img ... src="/_layouts/images/ichtm.gif"></a></td>
I think you can slurp that into an array, assign a new var that's just the href stripped of path/filename. and .html, and use that to replace htm in the src tag.
Could you not just edit the DOCICON.xml to add the ".jpg.html" and ".docx.html" extensions in?
For a full listing of icon files see all "ic*.gif" files in the TEMPLATE\IMAGES directory under the 12 hive. Unfortunately, this will not solve your problem, but this is where you can change it based on the extension, if you so choose.
Note that a blog I wrote a while back has a different focus, but does discuss where the icons come from: http://wiki.threewill.com/display/is/2007/10/14/External+Link+for+Editing+a+SharePoint+Document.