I am trying to use kml to implement a heirarchy of regions as describe in
KML 2.1 Tutorial
I would like to have a feature(polygon or icon) representing a region and when the region becomes active I would like to display a feature representing each of the regions immediate children but no longer display the icon representing the parent region.
An example would be if I had a region representing Canada and a placemark in the middle of the region. When the Canada region becomes active I want the canada placemark to disappear and want to display placemarks over the provinces of Canada(a region and placemark for BC, Alberta ect.). Then when the BC region became active I would like to replace the bc placemark with placemarks for cities in bc.
Any help would be greatly appreciated.
Thank you.
You are on the right track, Regions are what you want. Check out this page for more info on how to use them
http://code.google.com/apis/kml/documentation/regions.html
In particular, you need to understand the Level of Detail (LOD). The LOD determines the view boundaries that activates and deactivates the region. In the end you need to create Regions in this format.
<Region>
<LatLonAltBox>
<north>50</north>
<south>45</south>
<east>28</east>
<west>22</west>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
<maxLodPixels>1024</maxLodPixels>
</Lod>
</Region>
You can set -1 so the region is ALWAYS shown, no matter how far someone zooms OUT or if you use the value above (128) that means that the bounding box you set, must take up 128x128 pixels of the viewers screen before it gets activated (seen).
The is what you use to turn the view off as they zoom in. Or leave at -1 so it never turns off no matter how far someone zooms IN.
For your question, you would have a region that contains a placemark in the middle of Canada. That region would have a minlodpixels of -1 and a maxlodpixels that corresponds with the minlodpixels of another region (which shows the placemarks in the provinces) I would make a region for each province seperately.
The trick is working out the boundaries of the - I use a square polygon with four points and then look at its code to extract the etc
Actually, here is a great page to show you how to create regions - make sure you download the kml called 'Screen Overlay Size Guide' - it makes things a LOT easier
http://earth.google.ca/intl/en_ca/outreach/tutorial_region.html
I am trying to do the same thing and came up with a solution that works however it requires many calls to the server.
In your base kml loaded from http://example.com/zones.kml you would have
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<Document id="base">
<Folder id="1_folder">
//Region responsible for hiding the current (Canada) Placemark when zoomed in and made inactive ALSO responsible for hiding children(BC, Alberta...) Placemarks when active
<Region>
<LatLonAltBox>
<north>74.79903411865234</north>
<south>41.508766174316406</south>
<east>-52.03630065917969</east>
<west>-139.96746826171875</west>
</LatLonAltBox>
<Lod>
<maxLodPixels>
1024
</maxLodPixels>
</Lod>
</Region>
//NetworkLink that hides children Placemarks when zooming out
<NetworkLink>
<refreshVisibility>1</refreshVisibility>
<Link>
<href>http://example.com/1/hide_children.kml</href>
<viewRefreshMode>onRegion</viewRefreshMode>
</Link>
</NetworkLink>
//The Canada Placemark
<Placemark id="1">
<name>Canada</name>
<Point>
<coordinates>-96.00188446044922,58.153900146484375</coordinates>
</Point>
</Placemark>
//Networklink for Loading Children While Zooming in
<NetworkLink>
<refreshVisibility>1</refreshVisibility>
// Same Region as above but with minLodPixels instead of maxLodPixels
<Region>
<LatLonAltBox>
<north>74.79903411865234</north>
<south>41.508766174316406</south>
<east>-52.03630065917969</east>
<west>-139.96746826171875</west>
</LatLonAltBox>
<Lod>
<minLodPixels>1024</minLodPixels>
</Lod>
</Region>
<Link>
<href>http://example.com/zones/1.kml</href>
<viewRefreshMode>onRegion</viewRefreshMode>
</Link>
</NetworkLink>
</Folder>
</Document>
</kml>
This requires two more kml files that are loaded to hide or show the children of a particular placemark.
The kml for hiding the children would be loaded from http://example.com/1/hide_children.kml and contains the networklinkcontrol to hide the children
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<NetworkLinkControl>
<Update>
<targetHref>http://example.com/zones.kml</targetHref>
<Change>
<Folder targetId="1_children"><visibility>0</visibility></Folder>
</Change>
</Update>
</NetworkLinkControl>
</kml>
The kml for showing the children would be loaded from http://example.com/1.kml and contains the networklinkcontrol to show the children the children
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<NetworkLinkControl>
<Update>
<targetHref>http://example.com/zones.kml</targetHref>
<Create>
<Folder targetId="1_folder">
<Folder id='1_children'>
//This folder is the same as the original zone
<Folder id="2_folder">
//Empty region if the zone has no children
<Region></Region>
//No need for networklink to hide children if zone has no children
//Placemark
<Placemark id="2">
<name>BC</name>
<Point>
<coordinates>-122.95623779296875, 50.06098937988281</coordinates>
</Point></Placemark>
</Folder>
//Same for other Provinces
//<Folder id="3_folder"></Folder>
//<Folder id="4_folder"></Folder>
</Folder>
</Folder>
</Create>
</Update>
</NetworkLinkControl>
</kml>
It would be best if you could define 2 different regions one for minLod and one for maxLod so you didn't need to have so many calls to servers and you didn't have to call the server to load children you have already loaded but I have not figured out how to do this yet.
This need to be optimized quite a bit. Please let me know if anyone can help find a more direct way of doing this. Thanks
Related
I am trying to use the google earth pro desktop application for visualizing IoT sensor data at different locations. Unfortunately, due to the limitations of google earth, I am unable to visualize 4GB of kml file at a time, as it throws the error "empty KML file".
I tried changing the memory cache limits under Tools -> Options -> Cache and there was no use.
I tried splitting the 4GB kml file into multiple smaller 70MB files and opening multiple files in google earth. It is becoming unresponsive and is loading very slow after opening two files.
The data is timeline data with sensor values from different locations. We need to visualize all (at least half) data so that we can use the timeline slider and see the changes over time.
It would be great to get some suggestions/alternatives to solve the issue.
Thanks.
If a KML file is very large then trying to display all the features at once can crash Google Earth Pro, affect performance with sluggish response, etc. Large KML files can be viewed in Google Earth if all or some of these techniques are applied to the KML.
NetworkLink
Folder Radio style or explicit visiblity=0
Number of Points per feature and geometry simplification
NetworkLink
A root .kml file can reference all the sub-KML files, but the referenced sub-files should have the visibility off so the user must manually check it to be visible. This will prevent all the data from being displayed all at once.
Here is the structure of the root KML file:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<NetworkLink>
<name>NetworkLinked sub-item1</name>
<visibility>0</visibility>
<Link>
<href> kml1.kml </href>
</Link>
</NetworkLink>
<NetworkLink>
<name>NetworkLinked sub-item2</name>
<visibility>0</visibility>
<Link>
<href> kml2.kml </href>
</Link>
</NetworkLink>
...
</Document>
</kml>
Radio Folder
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> kml1.kml </href>
</Link>
</NetworkLink>
<NetworkLink>
<name>NetworkLinked sub-item-2</name>
<visibility>0</visibility>
<Link>
<href> kml2.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.
I have global data for fires around the world covering three days. Projecting the entire data into one kml ends up in huge kml. I tried to break up the data in to smaller regions and also smaller time intervals.
So I have hundreds of regions covering the whole globe and data for each of these regions is divided into 6 kmls (time span of 12 hours in each) to cover 3 days.
Th problem is that even after dividing the global data into smaller chunks, once I load the master file, GE wants to load the entire data and becomes too slow. Could there be a better way of doing this or maybe highlight what I might be doing wrong?
the overview of my kml files is as follows:
the master kml :
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Region>
<LatLonAltBox>
<north>90</north>
<south>-90</south>
<east>360</east>
<west>0</west>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
<maxLodPixels>1024 </maxLodPixels>
</Lod>
</Region>
<NetworkLink>
<name> Region NHAf</name>
<TimeSpan>
<begin>2011-06-01T00:30:00Z</begin>
<end>2011-06-04T00:30:00Z</end>
</TimeSpan>
<Region>
<LatLonAltBox>
<north>30</north>
<south>0</south>
<east>60</east>
<west>-30</west>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
<maxLodPixels>1024 </maxLodPixels>
</Lod>
</Region>
<Link>
<href>NHAf_base.kml</href>
<viewRefreshMode>onRegion</viewRefreshMode>
</Link>
</NetworkLink>
...
//more network links for other regions
</Document></kml>
This network links for different regions are further linked to sub-regions and the whole time span is also divided into smaller kmls :
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Region>
<LatLonAltBox>
<north>30</north>
<south>0</south>
<east>60</east>
<west>-30</west>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
<maxLodPixels>1024 </maxLodPixels>
</Lod>
</Region>
<Folder>
<name>NHAf 1 0050</name>
<NetworkLink>
<name> Region 1 resolution 0050</name>
<TimeSpan>
<begin>2011-06-01T00:30:00Z</begin>
<end>2011-06-01T12:30:59Z</end>
</TimeSpan>
<Region>
<LatLonAltBox>
<north>30</north>
<south>10</south>
<east>-10</east>
<west>-30</west>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
<maxLodPixels>1024 </maxLodPixels>
</Lod>
</Region>
<Link>
<href>NHAf_1_hr01_frpfire_20110601_1130_0050_1.kml</href>
<viewRefreshMode>onRegion</viewRefreshMode>
</Link>
</NetworkLink></Folder>
<Folder>
<name>NHAf 1 0050</name>
<NetworkLink>
<name> Region 1 resolution 0050</name>
<TimeSpan>
<begin>2011-06-01T13:30:00Z</begin>
<end>2011-06-01T23:30:59Z</end>
</TimeSpan>
<Region>
<LatLonAltBox>
<north>30</north>
<south>10</south>
<east>-10</east>
<west>-30</west>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
<maxLodPixels>1024 </maxLodPixels>
</Lod>
</Region>
<Link>
<href>NHAf_1_hr01_frpfire_20110601_2330_0050_1.kml</href>
<viewRefreshMode>onRegion</viewRefreshMode>
</Link>
</NetworkLink></Folder>
...
//more network links till end of time step
//more network links with different sub-regions
</Documents>
</kml>
If you have multiple time periods split into multiple KML files then you can preselect the default time loaded at startup with the KML extension <gx:TimeSpan> in the root Document element of the KML file. This initializes the time slider for this time interval. For it to work, you must add a Camera or a LookAt element with a <gx:TimeSpan>.
<?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">
<Document>
<LookAt>
<gx:TimeSpan>
<begin>2011-06-01T13:30:00Z</begin>
<end>2011-06-01T23:30:59Z</end>
</gx:TimeSpan>
<longitude>...</longitude>
<latitude>...</latitude>
<altitude>...</altitude>
<heading>...</heading>
<tilt>...</tilt>
<range>...</range>
</LookAt>
...
You can add the TimeSpan to your KML in Google Earth with these steps:
Orient the view you want to startup with
Right-mouse click the root KML element and select Properties
Click View tab
Click 'Snapshot current view'
Select/edit the start and end time you want start with
Click OK
Reference: https://developers.google.com/kml/documentation/kmlreference#gxtimespan
I want to get coordinates every second and update the track on google earth in the kml file
I know i need a network link with an update that is added coordinates with the time and refresh it every second but i couldn't find any complete examples that show this and the update part is confusing me. I was wondering if someone could write out a simple example?
If you want to generate KML and update on a regular interval then you create a root KML such as this:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<NetworkLink>
<name>NetworkLink example</name>
<Link>
<href>http://...</href>
<refreshMode>onInterval</refreshMode>
<refreshInterval>5</refreshInterval>
</Link>
</NetworkLink>
</kml>
If your area of interest is a "small" or locallized then you may want to add a Region to the NetworkLink and viewRefreshMode element with onRegion value to only refresh when the region is active (e.g., within the current view).
<NetworkLink>
<name>NetworkLink example with Region</name>
<Region>
</Region>
...
<Link>
<href>http://...</href>
<refreshMode>onInterval</refreshMode>
<refreshInterval>5</refreshInterval>
<viewRefreshMode>onRegion</viewRefreshMode>
</Link>
</NetworkLink>
For NetworkLinkControl a tutorial can be found here with a working example.
https://developers.google.com/kml/documentation/updates
I have just started to learn how to manipulate the KML files. here is a problem that I do not know how to overcome.... I created a polygon and added a description to be shown as a balloon, but it appears as soon as Google Earth starts working before the polygon can be seen. what I want is to show the balloon from a specific distance where the polygon appears(for example in the range distance of LookAt element).
anybody knows how to manage that?
my code follows:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" mlns: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">
<LookAt>
<longitude>17.99514610290434</longitude>
<latitude>59.36293893395309</latitude>
<altitude>0</altitude>
<range>597.51212259908</range>
<tilt>52.34415598649959</tilt>
<heading>105.3974737169693</heading>
</LookAt>
<Placemark>
<name>Stadium</name>
<description>
<![CDATA[
this is <b><i>Råsunda soccer stadium</i></b>
]]>
</description>
<gx:balloonVisibility>1</gx:balloonVisibility>
<styleUrl>#msn_ylw-pushpin</styleUrl>
<Polygon>
<extrude>1</extrude>
<tessellate>1</tessellate>
<altitudeMode>absolute</altitudeMode>
<outerBoundaryIs>
<LinearRing>
<coordinates>
17.99514610290434,59.36293893395309,100 17.99651951950199,59.36209399425741,100 17.99752330705672,59.36252751885282,100 17.99613146514916,59.36335387902954,100 17.99514610290434,59.36293893395309,100
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
</Document>
</kml>
Normally you can skip rendering the polygon until you get "close" enough to it as defined by a Region element which is determined by calculating when a given area maps to a min or max # of pixels.
Also, the <gx:balloonVisibility> tag forces the description balloon to appear when the KML is loaded regardless of whether Region is active. Adding a Region direct in the KML still shows the popup balloon.
To do what you want to do, you must wrap the KML file with a second KML file with a NetworkLink with a Region that loads the seconds KML only when the region is active (aka close enough) at which time the description is displayed along with the polygon.
<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<LookAt>
<longitude>17.99514610290434</longitude>
<latitude>59.36293893395309</latitude>
<altitude>0</altitude>
<heading>105.3974737169693</heading>
<tilt>52.34415598649959</tilt>
<range>597.51212259908</range>
</LookAt>
<NetworkLink>
<Region>
<LatLonAltBox>
<north>59.363792</north>
<south>59.361556</south>
<east>17.998029</east>
<west>17.994443</west>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
<maxLodPixels>-1</maxLodPixels>
</Lod>
</Region>
<Link>
<href>target.kml</href>
</Link>
</NetworkLink>
</Document>
</kml>
And target.kml file contains the original KML you gave:
<?xml version="1.0" encoding="ISO-8859-1"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark>
<name>Stadium</name>
...
</Placemark>
</kml>
You can change the distance the feature + balloon appears by adjusting the minLodPixels value and/or the size of the region. At present the feature will display when the region defined by area surrounding the polygon is at least 128 pixels on the screen. Change to 32 or 64 and/or make the region area larger to make it appear quicker.
Note Google Earth client doesn't give you a tool to edit or even see the Region bounding boxes on the map so debugging this is tricky. You can paste your KML into this tool to generate KML making the Region bounding area visible. This helps to debug Regions more easily.
I have created a network link that references another KML file with actual data to be loaded into Google Earth. My issue is that the number of points in the referenced KML file is so large that it crashes Google Earth if the KML file folder underneath the Places tab in Google Earth is set to "Allow this folder to be expanded" (right-click KML, properties). By default, this checkbox is checked. I want to make it so that for every network link I create the folder by default will not be expandable.
I have looked up checkHideChildren in Google Earth KML tutorials, but that line provides no results, and I am not entirely sure where I am supposed to place the line in the Network Link KML.
Here is example code, if you could point me in the direction where to place this line of code, or an entirely different approach, it would be greatly appreciated!
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<NetworkLink>
<name>
CPU
</name>
<refreshVisibility>1</refreshVisibility>
<Link id="GPS_Plotter Updater">
<href>CPU.kml</href>
<Style id="style1"><ListStyle>
<listItemType>checkHideChildren</listItemType> <-- this is the line that should be hiding the children points of the KML!
</ListStyle>
</Style>
<styleUrl>#style1</styleUrl>
<refreshMode>onInterval</refreshMode>
<refreshInterval>1</refreshInterval>
<viewRefreshMode>onRegion</viewRefreshMode>
<viewRefreshTime>1</viewRefreshTime>
</Link>
</NetworkLink>
</kml>
Try putting the Style element in the NetworkLink, not the Link element. Link doesn't take a style selector, but NetworkLink does. If that doesn't work, try a listItemType of radioFolder instead.
In addition to Mano Marks' suggestions you also need to move the styleUrl element to the NetworkLink otherwise it won't apply. Note in your example you have viewRefreshMode=onRegion but don't have a region defined for it.
Here's the complete working example to suppress the NetworkLink contents.
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<NetworkLink>
<name>CPU</name>
<styleUrl>#style1</styleUrl>
<Style id="style1">
<ListStyle>
<listItemType>checkHideChildren</listItemType>
</ListStyle>
</Style>
<Region>
<!-- define region here -->
</Region>
<refreshVisibility>1</refreshVisibility>
<Link id="GPS_Plotter_Updater">
<href>CPU.kml</href>
<refreshMode>onInterval</refreshMode>
<refreshInterval>1</refreshInterval>
<viewRefreshMode>onRegion</viewRefreshMode>
<viewRefreshTime>1</viewRefreshTime>
</Link>
</NetworkLink>
</kml>
You can catch errors like this by validating your KML. Try using the Galdos KML Validator.