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.
Related
I'm using SimpleKML to create a list of ~600 geotagged pictures (where each pin has an image as the description. So I click one of the pins on the map and it shows the picture I took at that coordinate).
The KMZ file is roughly 1GB and doesn't seem to open in Google Earth Pro. I've been looking around online and it seems that it may be too large of a file size to open. However, I have seen that Earth is capable of showing over a million coordinates. If I don't add the images as the description, the file shrinks to ~5kb and is able to work.
How can I open the file keeping the images as the description? Is there indeed an upper limit to file size?
(Note: I'm not sure if it's a Python/programming question, or Google Earth question so for now I am assuming it's a generic Google Earth question).
Google Earth Pro has both 32-bit and 64-bit versions. The 32-bit version limits access to 2GB memory and A 1-2 GB KMZ file is most likely larger than 2 GB when uncompressed which exceeds the memory available to Google Earth.
Google Earth itself can handle many GBs of data but not all at once. The only way to make that much data available to Google Earth is to have the KML file load a subset of the pictures at a time.
If the geotagged pictures are physically separable then you could create multiple KMLs where each KML represents a region and the photos in that region. Each KML file can be referenced by a parent KML file via a NetworkLink. NetworkLink would require a Region element to specify when to load the KML file with the geotagged pictures in a given region. The Region contains a bounding box (<LatLonAltBox>) that describes an area of interest defined by geographic coordinates and altitudes. In addition, a Region contains a LOD (level of detail) extent that defines a validity range of the associated Region in terms of projected screen size in pixels.
Your root KML would be structured like this:
<Document>
<NetworkLink>
<Region>
...
</Region>
<Link>
<href>1.kml</href>
</Link>
</NetworkLink>
...
</Document>
Getting the Regions to work takes trial and error. You can measure the "screen" pixels dimensions for Regions with this KML screen ruler.
Here are two tutorials for working with Regions:
https://developers.google.com/kml/documentation/regions
https://www.google.com/earth/outreach/learn/avoiding-overload-with-regions/
Alternatively, you can create several KMZ files each with a subset of geotagged pictures. You could tie the sub KMZ files together with a parent KML file with radioFolder List style and NetworkLinks with each of the KMZ files. This allows you to select any of the sub-KMZ files with photos but only one at a time to prevent memory overload.
<Document>
<Style id="radioStyle">
<ListStyle>
<listItemType>radioFolder</listItemType>
</ListStyle>
</Style>
<styleUrl>#radioStyle</styleUrl>
<NetworkLink>
<visibility>0</visibility>
<Link>
<href>1.kml</href>
</Link>
</NetworkLink>
<NetworkLink>
<visibility>0</visibility>
<Link>
<href>2.kml</href>
</Link>
</NetworkLink>
</Document>
If you want one of the KML files to be viewable by default when opened in Google Earth then change its visibility to "1" and leave the others as "0".
The SimpleKML API supports networklinks, Regions, KMZ, etc. so it is best to experiment and try different KML output to see what works better.
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>
I have created a kml file with 15.439 contour and each one has 360 coordinates. The file size is 369Mb.
When I try to open the file, Google Earth shows a message saying:
"Google Earth encountered a problem and needs to close. We are sorry for the inconvenience."
Is there any size restrictions for KML files? I have verified the kml code and it's ok. It works perfectly with 950 contours and 16Mb.
Is there any other program able to open this kml file?
Thanks for the help!
jluiz20
Your KML file has over 3 million coordinates which is hitting some upper limit for a single KML file in Google Earth. You can scale to that number of contours/features and more if you break it up into smaller KML files, load them in a parent KML via NetworkLinks, and use Regions to only load those features that are in view.
Google Earth can scale up to millions of points and features but not all at once.
If the 15,439 features are geographically separable then you can break up the KML by some geographic grouping or fixed gridded area each in its own KML. Maybe 15 KML files each with 1000 features might be a good starting place.
The parent KML should have each NetworkLink with the appropriate Region and Level of detail (Lod) element to prevent all of the KML files from loading all at once.
Here's the structure of the parent KML file:
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<NetworkLink>
<name>area 1</name>
<Region>
<LatLonAltBox>
<north>xx</north>
<south>xx</south>
<east>xx</east>
<west>xx</west>
</LatLonAltBox>
<Lod>
<minLodPixels>32</minLodPixels>
</Lod>
</Region>
<Link>
<href>1.kml</href>
</Link>
</NetworkLink>
<NetworkLink>
<name>area 2</name>
...
</NetworkLink>
...
</Document>
</kml>
Yes there are restrictions. Check out the docs under
https://developers.google.com/kml/documentation/mapsSupport?csw=1
I ran into similar problems with a 60mb file.
You can use the workaround using Network links but according the docs they only support less than 10.
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 .
Is it possible to create one KMZ file that is composed of several smaller KMZ files? I would prefer to not have to manually merge the actual KML entities, but I will if that's the only option.
A KMZ file can have any number of inner KML files (NOT KMZ files). But the first entry in the KMZ file must be the root KML file (typically named doc.kml), which may include network links with references to other KML or KMZ files. Several inner KML files, for example, could reference a shared style (in another KML file) via relative URLs.
The inner KML files can nest to any level of depth to other KML files so you can create a hierarchy of nested KML files.
KMZ files within KMZ files is not supported in Google Earth so that is not recommended. If you want a root KMZ file to reference other sub-KMZ files then the sub-KMZ files should not be sub-entries of the root KMZ file but located at the same relative context in the web server or file system.
Here is what a root KML file in a KMZ file would look like that includes at least two sub-KML files.
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<NetworkLink>
<Link>
<href>test1.kml</href>
</Link>
</NetworkLink>
<NetworkLink>
<Link>
<href>test2.kml</href>
</Link>
</NetworkLink>
...
</Document>
</kml>
You can set visibility tag to 0 or add radio folders to selectively load inner KML files or add Region elements to load when given region is active. This would be needed to scale to lots of Features to achieve good performance.
Reference: https://developers.google.com/kml/documentation/kmlreference#networklink