Dynamically updating KML file based on certain conditions - kml

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

Related

Updating Google KMZ Popup Contents & Removing "Directions" in FME

By default a KML balloon will contain links "Directions to Here" and "Directions from Here" (driving directions).
I want to know, how to remove these links from the balloon using FME, as well as use HTML to set KML Balloon content, URL links and images, such as pngs, jpegs, and tiffs.
Also, I will appreciate if there is a workaround other than FME, to do the same, my objective is to remove the data from google kmz which I don’t need and only want to show that data which is required.
What you will want to end up with in the KML file is a BalloonStyle for your balloon content, which looks like: <BalloonStyle><text>...</text></BalloonStyle>, either shared at the top of the KML file, or inline in each placemark/feature. Your BalloonStyle can contain with either static HTML/Text content for the balloon, or an HTML template that can be filled in with basic data (name, description, etc.) or ExtendedData fields from each feature. When you specify balloon content using BalloonStyle, it will leave leave out the directions info. It will also not include the name at the top of the balloon by defautl, so you may want to include that in your content or template.
For more on KML BalloonStyles, see:
https://developers.google.com/kml/documentation/kmlreference#balloonstyle
and:
https://developers.google.com/kml/documentation/extendeddata
I don't know much about FME, but looks like it's possible to do this using AttributeCreator. For more see these instuctions:
https://community.safe.com/s/article/kml-balloon-contents-removing-directions

Google earth sequential placemarks on a time delay

I have a KML file with a few different placemarks all around the globe. I would like to flyto the first placemark and display it's balloon, wait a minute or two, then flyto the next placemark, and repeat this process until all of the placemarks have been shown.
I think I might be able to achieve this by putting all the placemarks into a tour but this doesn't seem like the right approach. I'm going to be refreshing the KML from a server and I'm not sure how a tour would react to that (e.g., I think you have to always click play before starting a tour).
If this isn't possible I may have to place just a single placemark in the KML file and then keep refreshing the file with a different placemark. I think that approach might be bad though because it will be refreshing a lot more.
I ended up putting one placemark per KML file. I wrote a program in Java that uses the Saxon processor and an XSLT stylesheet to create multiple KML files with just a single placemark per file then using this tutorial I was able to cycle through the KML files one-by-one.
When doing this locally on my machine I created two folders. Folder A housed all the KML files. Folder B would house only one KML file which would be the file expected from the KML NetworkLink tag. In the Java program I had a timer thread that sequentially deletes the single file in Folder B, cuts a file out of Folder A, moves it into Folder B, then renames the newly placed file the common name which the KML NetworkLink tag expects. I hope this helps and the link will help this to make more sense.
(Base KML file which is loaded into Google Earth - Basically tells Google Earth to look for the file called every10.kml every 10 seconds. If we swap that file out, say, every 9 seconds, then once it's refreshed by Google Earth it will be a new KML file thus showing the new placemark)
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<Document>
<NetworkLink>
<Link>
<href>every10.kml</href>
<refreshMode>onInterval</refreshMode>
<refreshInterval>10</refreshInterval>
</Link>
</NetworkLink>
</Document>
</kml>

How does a KML file help in loading maps in the Google Earth?

https://developers.google.com/kml/documentation/kml_tut
KML uses a tag-based structure with nested elements and attributes and is based on the XML standard.
So, KML is basically a "text" file, it doesn't contain the maps.
How does Google Earth use KML files to show maps? Does it treat KML file as an "index" to know which of its maps to pick when user presses x button?
KML is an XML language used to annotate the Earth with points, lines, polygons, 3d models, and overlays.
As an analogy, HTML is a language to structure and represent textual information and multi-media in a 2-D document context within a web browser. Likewise, KML is a language to structure and represent geospatial and temporal entities on a map and show in "earth browsers" such as Google Earth.
Specifically KML allows you to :
Specify icons and labels to identify locations on the surface of the planet
Create different camera positions to define unique views for geographic features
Define image overlays to attach to ground or screen
Define styles to specify KML feature appearance
Organize KML features into hierarchies
Locate and update retrieved KML documents from local or remote network locations
KML is a structured format of data that tells Google Earth how to display the data (point, line, icons, colors, styles, etc.) and where to draw it (longitude and latitude optionally at a given altitude). KML is simply a data exchange format.
Here's a simple KML file:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Placemark>
<name>New York City</name>
<description>New York City</description>
<Point>
<coordinates>-74.006393,40.714172</coordinates>
</Point>
</Placemark>
</Document>
</kml>
As an "index", a KML file by default will load at the center point that covers all includes features in the KML, but that can be overridden if a LookAt or Camera is defined. If you click on a Placemark it will fly to that feature as defined by its coordinates.
Clicking on such a placemark in Google Earth will fly to that location, which for the example above happens to be New York City.
KML is a "text" file that can also be packaged and distributed in a "KMZ" file, which is a ZIP file with .kmz file extension.
More details about KML can be in the OGC KML Standard # 07-147r2 .

Building large KML file

I generate KML files which may have 50,000 placemarks or more, arranged in Folders based on a domain-specific grouping. The KML file uses custom images which are packed in to a KMZ file.
I'm looking to breakup the single KML file in to multiple files, partitioned based on the grouping, so rather than having 1 large document with folders, i'd have a root/index KML file with folders linking to the smaller KML files.
Is this possible though? I think that a KMZ file can contain only 1 KML file, regardless of where it's located or its name, in the zip. Furthermore, I'm not exactly sure how a KML file can link to another KML file. Is the only way to have it as a <NetworkLink> to a local file? Can a <NetworkLink> work to link to a file local in the same KMZ?
By design you can have multiple KML files within a single KMZ file. That way you can bundle many KML files in a single KMZ file that is downloaded, sent via e-mail or accessed offline.
Google Earth can scale to a large number of features (50,000 or much larger) in a single KMZ file if the features are split into multiple KML files and the KML is defined such that all the sub-KML files are not displayed at once. KML provides mechanisms to control which features or sub-KML files are displayed using time, region, or altitude level filtering.
Large KML files can scale using any of the following techniques:
NetworkLinks
Regions
Folder Radio style or explicit visiblity=0
Number of Points per feature and geometry simplification
NetworkLinks
You can have any level of NetworkLinks from within your root KML file from flat (single KML file with Networklinks to all other KML files within the KMZ) to deep (with each KML file with a NetworkLink to other KML files each with its own NetworkLink). Depends on how you need to structure your KML and how large the data is.
The key is that Google Earth chooses the first KML as the root KML file so you must ensure that the first file (typically named doc.kml) is the root KML file that loads the other KML files via network links. A common structure is to include additional KML files in a "kml" sub-folder to differentiate it from the root KML file.
Here's a KMZ example with 4 file entries: root KML file (doc.kml) that contains a NetworkLink to "kml/sub1.kml" and another to "kml/sub2.kml", which in turn has a NetworkLink to "sub3.kml" also in "kml" sub-folder.
== test.kmz ==
+doc.kml
NetworkLink > kml/sub1.kml
NetworkLink > kml/sub2.kml
+kml/sub1.kml
+kml/sub2.kml
NetworkLink > sub3.kml
+kml/sub3.kml
Here is the structure of such a doc.kml file:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<NetworkLink>
<name>NetworkLinked sub-item</name>
<Link>
<href> kml/sub1.kml </href>
</Link>
</NetworkLink>
<NetworkLink>
<name>NetworkLinked sub-item</name>
<Link>
<href> kml/sub2.kml </href>
</Link>
</NetworkLink>
...
</Document>
</kml>
As a best practice if you include more than one NetworkLink with time-based features in a parent KML file then add a <TimeSpan> element to the NetworkLinks including the full range of time for that collection of features otherwise Google Earth will automatically load the entire file at startup.
<NetworkLink>
<TimeSpan>
<begin>2007-01-14T01:00:00Z</begin>
<end>2007-01-14T02:00:00Z</end>
</TimeSpan>
<Link>
<href>...</href>
</Link>
</NetworkLink>
Regions
A Region
affects visibility of a Placemark's geometry or an Overlay's image. Regions combined with NetworkLinks enable access to massive amounts of data in KML files. A region can optionally have a min and max altitude for altitude level filtering.
For more details, here's a tutorial on Regions in KML
https://developers.google.com/kml/documentation/regions
Radio Folders
You can further restrict what is displayed at a given time using radio folders.
Here's a radio folder example allowing the user to only choose one of the NetworkLinks at a time.
This is used when the content is mutually exclusive and only one set of features should appear at any given time.
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Style id="rf">
<ListStyle>
<listItemType>radioFolder</listItemType>
</ListStyle>
</Style>
<Folder>
<name>One at a time example</name>
<open>1</open>
<description>Link 1 visible by default</description>
<styleUrl>#rf</styleUrl>
<NetworkLink>
<name>NetworkLinked sub-item-1</name>
<Link>
<href> kml/sub1.kml </href>
</Link>
</NetworkLink>
<NetworkLink>
<name>NetworkLinked sub-item-2</name>
<visibility>0</visibility>
<Link>
<href> kml/sub2.kml </href>
</Link>
</NetworkLink>
</Folder>
</Document>
</kml>
Number of Points per feature and geometry simplification
Size of the KML file and number of features is not the only issue to consider. A KML file with a single hi-res polygon having 350K points and 7000 inner holes can cause Google Earth performance issues. Such geometries would need to be simplified and the number of points reduced. You can use QGIS to open a KML file then apply a simplify algorithm on the polygon. In QGIS, select Vector menu -> Geometry tools -> Simplify then save the result.
Yes you can use a networklink to accomplish this and as far as I know it's the only way to do what you ask. And yes you can reference local files in Network links
See: http://code.google.com/intl/nl-NL/apis/kml/documentation/kml_tut.html (search for "Network Links") where it says:
A network link contains a element with an (a hypertext
reference) that loads a file. The can be a local file
specification or an absolute URL. Despite the name, a <NetworkLink>
does not necessarily load files from the network. The <href> in a
link specifies the location of any of the following:
• An image file used by icons in icon styles, ground overlays, and screen overlays
• A model file used in the element
• A KML or KMZ file loaded by a Network Link
No you can't reference to another file inside a kmz. A kmz can only contain 1 kml file (it can contain other type of files though) You can find the layout of kmz files and what may be put in them here Specifically note the following section:
2.Put the default KML file (doc.kml, or whatever name you want to give
it) at the top level within this folder. Include only one .kml file.
(When Google Earth opens a KMZ file, it scans the file, looking for
the first .kml file in this list. It ignores all subsequent .kml
files, if any, in the archive. If the archive contains multiple .kml
files, you cannot be sure which one will be found first, so you need
to include only one.)
One final remark is that your question doesn't tell anything if you need these 50.000 placemarks as offline files or not. If you could serve them dynamically you could use the region based links where GE will tell you the viewing region of the client so you can return a small subset of the waypoints (only the ones that are inside the users view) For more info this is the link to click on.

How to properly update Google Earth KML using NetworkLinkControl and the Java API for KML (JAK)?

I'm building an application that serves up data to a standalone Google Earth client. I want to send over an initial set of data, then update it dynamically using <NetworkLinkControl> and <Update><cookie> tags as things change on the server. I'm generating the KML using the Java API for KML (JAK) library. Unfortunately, while I can confirm that GE is refreshing my NetworkLink and pulling down the Updates I'm sending, none of my updates are showing up in GE. After lots of reading, it seems like it might be that the Update's <targetHref> might be the issue, but I'm 99.9% sure I'm sending over the same string.
Part of what has me confused is that I've seen conflicting info on whether or not the <cookie> element's value needs to be appended to <targetHref>. I did actually see one early prototype updating when I was serving up hand-written test KML files from a static server URL, so I suspect it's not. Actually, that's what's frustrating at the moment: I've seen updating work on my own machine, but can't get it working now with what looks like valid and correct KML.
The current setup looks like this (extraneous XML namespaces stripped for clarity; "$CLIENT_ID" is a GUID-like string):
Root KML file served from http://server/kml/${CLIENT_ID}:
<kml xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><NetworkLink>
<Link>
<href>http://server/kmlupdates/${CLIENT_ID}</href>
<refreshMode>onInterval</refreshMode>
<refreshInterval>1.0</refreshInterval>
<viewRefreshTime>0.0</viewRefreshTime>
<viewBoundScale>0.0</viewBoundScale>
</Link>
</NetworkLink></kml>
Initial content KML served from http://server/kmlupdates/${CLIENT_ID}:
<kml><NetworkLinkControl>
<minRefreshPeriod>0.0</minRefreshPeriod>
<maxSessionLength>-1.0</maxSessionLength>
<cookie>cookie=0|kmlRequestType=updates|projectID=6|lastUpdateSeenIndex=-1</cookie>
</NetworkLinkControl>
<Document id="myProject">
<name>My ProjectProject</name>
<Placemark id="pm1"><name>point1</name>
<Point><coordinates>-117.0,35.0</coordinates></Point>
</Placemark>
</Document></kml>
Later update KML served from http://server/kmlupdates/${CLIENT_ID}:
<kml><NetworkLinkControl>
<minRefreshPeriod>0.0</minRefreshPeriod>
<maxSessionLength>-1.0</maxSessionLength>
<cookie>cookie=0|kmlRequestType=updates|projectID=6|lastUpdateSeenIndex=0</cookie>
<Update>
<targetHref>http://server/kmlupdates/${CLIENT_ID}</targetHref>
<Change>
<Placemark targetId="pm1">
<name>Name changed by Update Change</name>
</Placemark>
</Change>
</Update>
</NetworkLinkControl></kml>
If anyone has any suggestions on what I'm missing here, I'd greatly appreciate it. Thanks!
My original version of the question left out two facts that turned out to be relevant: 1) I'm using the Java API for KML to generate this, and 2) the XML namespaces inside <kml>. I finally figured this out after reading this Google KML Group post for the umpteenth time.
The problem is the last XML namespace, "xmlns:xal". For some reason, removing that from the KML allows the <Update> tags to actually change the items in Google Earth. JAK doesn't let you change the namespaces, but you can strip it manually from the marshaled string.
Absolutely bizarre, but at least I found a solution.
As per https://developers.google.com/kml/documentation/kmlreference:
<xal:AddressDetails> is used by KML for geocoding in Google Maps only.
Currently, Google Earth does not use this element; use <address> instead.
I have some sample using different approach to do something else here maybe related to yours (as your purpose "send over an initial set of data, then update it dynamically using tags") :
https://sites.google.com/site/canadadennischen888/home/kml/auto-refresh-3d-tracking
Approach is that all changes are from server Restful service. Hope it helps. Details as :
How to make a dynamic Auto refresh 3D Tracking :
prepare a RestFul service to generate KML file from DB (KML sample as inside above link)
My other jsp code will generate a KMZ file which has a link to my Restful service. KMZ file has onInterval ( as in the bottom)
Jsp web page allow user to download KMZ file.
When Google Earth open KMZ file, Google Earth will auto refresh to get new data from that Restful service
Everytime refreshing, server will send the latest update KML data with new data to GE.
KMZ sample:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<NetworkLink>
<name>Dennis_Chen_Canada#Hotmail.com</name>
<open>1</open>
<Link>
<href>http://localhost:9080/google-earth-project/rest/kml/10001/20002</href>
<refreshMode>onInterval</refreshMode>
</Link>
</NetworkLink>
</kml>

Resources