Big picture: I'm writing my own KMLs using a custom KML writer in C++. I have a set of placemarks that share some (not all) properties. Currently I store the shared properties as properties of the parent folder the placemarks reside in. These KMLs are viewed in Google Earth.
Users gain access to view this data using a BalloonStyle linked to the ExtendedData stored within each placemark/folder. The placemarks share a balloonstyle for their unique data, and the shared data is displayed using the parent folder's balloon style when they click on the folder in Google Earth.
I can't afford to duplicate the shared data in each placemark, which is why I store it in the parent folder.
Alternative 1: Is there any way to provide a user-clickable link to the parent folder's balloon within the child's balloon?
Alternative 2: Is it possible to display another Placemark/Feature's data in a placemark's info balloon?
As far as I know, both alternatives are impossible.
Edit: Simplified example code:
<?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">
<Document>
<name>MyKml</name>
<Style id="Style8"> <!-- style for child point -->
<BalloonStyle>
<text>
Point: $[name]<br/>
Code: $[code]<br/>
Number of Points: $[numpts] <!-- Alt2: numpts belongs to the parent - this syntax is obviously wrong -->
Link to parent: $[parentid] <!-- Alt1: if I can't display the parent's properties, can I at least give a clickable link to it? -->
</text>
</BalloonStyle>
</Style>
<Style id="Style12"> <!-- style for parent folder -->
<BalloonStyle>
<text>
Point Group: $[name]<br/>
Number of Points: $[numpts]
</text>
</BalloonStyle>
</Style>
<Folder>
<name>Point Group 1</name>
<styleUrl>#Style12</styleUrl>
<ExtendedData>
<Data name="numpts">
<value>4</value>
</Data>
</ExtendedData>
<Placemark>
<name>PT1</name>
<styleUrl>#Style8</styleUrl>
<ExtendedData>
<Data name="code">
<value>TAT1</value>
</Data>
</ExtendedData>
<MultiGeometry>
<Point>
<coordinates>-121,47,110</coordinates>
</Point>
</MultiGeometry>
</Placemark>
<Placemark>
<name>PT2 - PT4</name>
<styleUrl>#Style8</styleUrl>
<ExtendedData>
<Data name="code">
<value>TAT2</value>
</Data>
</ExtendedData>
<MultiGeometry>
<Point>
<coordinates>-121.090,47.430,1224</coordinates>
</Point>
<Point>
<coordinates>-121.470,47.621,122</coordinates>
</Point>
<Point>
<coordinates>-121.990,47.121,122</coordinates>
</Point>
</MultiGeometry>
</Placemark>
</Folder>
</Document>
</kml>
Alternative 1: Is there any way to provide a user-clickable link to the parent folder's balloon within the child's balloon?
This is achieved using feature anchors where you can refer to and link to placemarks by its KML id using <a href="target"> in the description/balloon. If the target Feature has a LookAt or Camera element, the Feature is viewed from the specified viewpoint.
The href can be a fragment URL (that is, a URL with a # sign followed by a KML identifier).
You can also append an action to the URL with a semi-colon (;) and one of these qualifiers:
;flyto (default) - fly to the Feature
;balloon - open the Feature's balloon but do not fly to the Feature
;balloonFlyto - open the Feature's balloon and fly to the Feature
If you want to show the folder balloon from the point's you can update the BalloonStyle text as following and add "id" attribute to the Folder you want to refer to.
<Style id="Style8">
<BalloonStyle>
<text>
<![CDATA[
Point: $[name]<br/>
Code: $[code]<br/>
Number of Points: $[numpts]
<BR>Link to parent
]]>
</text>
</BalloonStyle>
</Style>
<Folder id="parent"> *** Must add "id" attribute to link to it ***
...
</Folder>
Alternative 2: Is it possible to display another Placemark/Feature's data in a placemark's info balloon?
Can't directly include metadata for another placemark in balloon of another but can link to it and switch to showing other's balloon by user clicking the link.
You could add links to the description of the placemarks to link to one another in the same way to link to Folder by its id then add $[description] place holder to the BalloonStyle text.
<Style id="style9"> <!-- style for child point -->
<BalloonStyle>
<text>
<![CDATA[
Point: $[name]<br/>
Code: $[code]<br/>
Link to parent
<br>$[description]
]]>
</text>
</BalloonStyle>
</Style>
...
<Placemark id="pt1">
...
</Placemark>
<Placemark id="pt2">
<name>PT2 - PT4</name>
<description>
<![CDATA[
Show P1<BR>
]]>
</description>
<styleUrl>#style9</styleUrl>
...
</Placemark>
Related
I have a working KML code displaying GPS'd surveyor markers on property boundary nominally coinciding with a town line. Now I want to do something a little more advanced:
Center the whole earth view over the place in question.
Draw the town line segment (a straight line connecting two corners ~10 km apart (which I had to change to a line connecting points 200 meters apart to stop the line from disappearing in hilly terrain when zooming in), automatically zooming in to a frame representing about 12 km high around the 10 km line, with a viewpoint elevation of 20 km.
Pause a few seconds.
Mark the GPS'd survey markers (using standard icons) and zoom in further to the shorter section of the town line framing my GPS'd markers (LookAt, 3700 meters range)
From this viewpoint, let my users manually navigate, zoom on individual marker icons, click on them for descriptions, etc. etc.
When I try to reorganize my code to add these stages, I get a message: "failed: Only a single root feature allowed within tag".
What am I doing wrong, and how should I be coding this?
Synopsis of code:
<?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">
<name>MHT-State boundary issues</name>
<!-- icons for historic stone corner monuments -->
<Style id="P.Star">
<IconStyle>
<Icon>
<href>
http://maps.google.com/mapfiles/kml/paddle/purple-stars-lv.png
</href>
<scale>0.25</scale>
</Icon>
</IconStyle>
</Style>
<!-- define blue(boundary) line between corners -->
<Style id="BlueLine">
<LineStyle>
<color>ffff0072</color>
<width>1</width>
</LineStyle>
</Style>
<!-- locate corners -->
<Placemark>
<name>B-H-R corner</name>
<styleUrl>#P.Star</styleUrl>
<description>Blandford-Hungtington-Russell corner, coordinates per MassDOT</description>
<Point><coordinates>-72.872182,42.216453</coordinates></Point>
</Placemark>
<Placemark>
<name>B-G-R corner</name>
<styleUrl>#P.Star</styleUrl>
<description>Blandford-Granville-Russell corner, coordinates per MassDOT</description>
<Point><coordinates>-72.895662,42.123925</coordinates></Point>
</Placemark>
<!-- draw town line between them -->
<Placemark>
<name>Blandford-Russell boundary</name>
<styleUrl>#BlueLine</styleUrl>
<LineString>
<tessellate>1</tessellate>
<altitudeMode>clampToGround</altitudeMode>
<coordinates>
-72.895662,42.123925,0
-72.895622,42.124,0
... (more intermediate coordinates in straight line)
-72.872182,42.216453,0
</coordinates>
</LineString>
</Placemark>
<!-- set wide viewpoint to see boundary from Granville to Huntington corners -->
<LookAt>
<longitude>-72.884</longitude>
<latitude>42.171</latitude>
<range>20000</range>
</LookAt>
<!-- pause 5 seconds -->
<gx:Wait>
<gx:duration>5</gx:duration>
</gx:Wait>
<!-- add legend -->
<ScreenOverlay>
<name>Boundary Legend</name>
<overlayXY x="0" y="0" xunits="fraction" yunits="fraction"/>
<screenXY x="0" y="0.1" xunits="fraction" yunits="fraction"/>
<rotationXY x="0" y="0" xunits="fraction" yunits="fraction"/>
<size x="0" y="0" xunits="fraction" yunits="fraction"/>
<Icon><href>files\BndyLegend.png</href></Icon>
</ScreenOverlay>
<!-- define yellow line for first Hull/DFW boundary segment -->
<Style id="YellowLine">
<LineStyle>
<color>FF14F0FF</color>
<width>1</width>
</LineStyle>
</Style>
<!-- icon styles
purple (P.) - before 1950
red (R.) - 1950-1999
green (G.) - 2000-2013
yellow (Y.) - 2014 on
white (W.) - uncertain
star (.Star) - end monument
diamond (.Dmnd) - waypoint stone/concrete monument
circle (.Cir) - pipe set in ground, stones or concrete
square (.Sq) - blaze
blank (.blnk) - blank
-->
<!-- icons for historic waypoint stone monuments -->
<Style id="P.Dmnd">
<IconStyle>
<Icon>
<href>
http://maps.google.com/mapfiles/kml/paddle/purple-diamond-lv.png
</href>
<scale>0.25</scale>
</Icon>
</IconStyle>
</Style>
... (more styles)
<!-- pre-GPS town line marker, Route 23, #2 -->
<Placemark>
<name>2</name>
<styleUrl>#P.Dmnd</styleUrl>
<description>old town line monument by state route 23, by Garmin eTrex</description>
<Point><coordinates>-72.88422,42.17023</coordinates></Point>
</Placemark>
... (more point placemarks)
<!-- set viewpoint directly over #7, from 3700 meters up -->
<LookAt>
<longitude>-72.879562</longitude>
<latitude>42.1872075</latitude>
<range>3700</range>
</LookAt>
</Document>
</kml>
What happens:
Initial view of globe, without rotation or zoom appears, then this window pops up:
"Open of file "C:\Users\DTM\Documents\MHT\abutting state parcel\boundary KML\Boundary GPS.kml" failed: Only a single root feature allowed within tag"
You're missing the <Document> tag near the top of your file. You already have the closing </Document> tag near the end, but seem to be missing the opening one, which should go between the <kml...> tag and the first <name> tag. So your file should have this structure:
<?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>
<name>MHT-State boundary issues</name>
...
</Document>
</kml>
For background, every KML must contain only one top-level element inside the <kml>...</kml> tags. That can either be ONE feature (like a Placemark, etc.) or it can be one "container": either a Document or Folder. So if you have a KML that will contain more than one Feature (or Style, etc.), then you need to wrap everything in at least one level of Document or Folder.
From the documentation:
A basic element contains 0 or 1 Feature and 0 or 1 NetworkLinkControl:
<kml xmlns="http://www.opengis.net/kml/2.2">
<NetworkLinkControl> ... </NetworkLinkControl>
<!-- 0 or 1 Feature elements -->
</kml>
A Feature Element is a single Placemark or a Document or Folder (either of which can contain multiple Placemarks):
<Feature>
Syntax
<!-- abstract element; do not create -->
<!-- Feature id="ID" --> <!-- Document,Folder,
NetworkLink,Placemark,
GroundOverlay,PhotoOverlay,ScreenOverlay -->
Document:
<Document>
Syntax
<Document id="ID">
<!-- inherited from Feature element -->
...
<!-- specific to Document -->
<!-- 0 or more Schema elements -->
<!-- 0 or more Feature elements -->
</Document>
Folder:
<Folder>
Syntax
<Folder id="ID">
<!-- inherited from Feature element -->
<name>...</name> <!-- string -->
...
<!-- specific to Folder -->
<!-- 0 or more Feature elements -->
You need to put your <Placemark> tags inside <Document> or <Folder> tag.
I have some symbols that I want to add to a KML file (for Google Earth). However, my symbols consist of multiple icons overlayed on top of each other. For other maps that I use I simply draw the icons on top of each other and control the selection/right click actions so that the user only sees it as one object, but in Google Earth if I add each overlayed icon as a separate placemark the user sees multiple objects when they click on it. Is there a way to add a single placemark in kml with multiple icons?
I wanted to do something like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:ns2="http://www.w3.org/2005/Atom" xmlns:ns3="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">
<Document>
<name>kmlTest</name>
<open>true</open>
<description>description</description>
<StyleMap id="Symbol0Map">
<Pair id="Symbol0MapPairNormal">
<key>normal</key>
<Style id="Symbol0normal">
<IconStyle id="Symbol0iconStyle">
<scale>1.0</scale>
<heading>0.0</heading>
<Icon>
<href>files/images/GenericGround_0.png</href>
</Icon>
<Icon>
<href>files/images/eqp_2.png</href>
</Icon>
</IconStyle>
<LabelStyle id="Symbol0labelStyle">
<color>FF00FFFF</color>
<colorMode>normal</colorMode>
<scale>0.0</scale>
</LabelStyle>
</Style>
</Pair>
<Pair id="Symbol0MapPairHighlight">
<key>highlight</key>
<!-- similar to above -->
</Pair>
</StyleMap>
<Folder>
<name>My Layers</name>
<visibility>true</visibility>
<open>true</open>
<Folder>
<name>My Layer</name>
<visibility>true</visibility>
<open>false</open>
<Folder>
<name>Symbols</name>
<visibility>true</visibility>
<open>false</open>
<Placemark id="Placemark0">
<visibility>true</visibility>
<open>false</open>
<description>Platform</description>
<styleUrl>#Symbol0Map</styleUrl>
<Point>
<coordinates>-123.1569,38.5962,0.0</coordinates>
</Point>
</Placemark>
</Folder>
</Folder>
</Folder>
</Document>
</kml>
where I just have multiple <Icon> tags (or multiple <IconStyle> tags). However, looking at the schema this is not valid and I tried it anyways and it only picks the last one.
Is this even possible or will I need to dynamically create rolled up icons in code and include those in my .kmz file?
A KML placemark can only have one icon image. You will need to combine (roll up) your icons into a single image and then apply that to the placemark.
I am using Google Earth 5.0 Client. I would like to update a KML file (loaded by a NetworkLink) by clicking on a hyperlink in the description/balloonStyle tag of one of its placemarks.
Here is an example:
A.kml
<?xml version="1.0" encoding="UTF-8"?>
<kml>
<NetworkLink>
<Link>
<href>http://www.example.com/B.kml</href>
</Link>
</NetworkLink>
</kml>
B.kml
<?xml version="1.0" encoding="UTF-8"?>
<kml>
<Document>
<Folder id="entities">
<Folder id="en1_folder">
<Placemark id = "en1_point">
<description>
<a href="http://www.example.com/getConnections.php?en=id1"
type="application/vnd.google-earth.kml+xml"> Get connections </a>
</description>
<Point>
<coordinates>...</coordinates>
</Point>
</Placemark>
</Folder>
There are about 500 such folders, each with its corresponding en# point
containing a description hyperlink.
</Folder>
</Document>
</kml>
If a user clicks on a hyperlink, I want to generate a set of LineStrings connecting that point to one or more other points.
For example, getConnections.php?en=id1 could generate a response like this:
<?xml version="1.0" encoding="UTF-8"?>
<kml>
<Update targetHref="http://www.example.com/B.kml">
<Change>
<Folder targetId="en1_folder">
<Placemark id="en1_connections">
<LineString>
<Coordinates>
(en1_coords), (en5_coords), (en7_coords)
</Coordinates>
</LineString>
</Placemark>
</Folder>
</Change>
</Update>
</kml>
This doesn't work in GE 5.0. I understand that Update is a child of NetworkLinkControl which in turn must be requested by a NetworkLink from the same domain as the KML that contains it.
I know there are several workarounds using one or more NetworkLinks, however I am curious to know if there still exists a way to directly update the same KML file by clicking on the description hyperlink.
Any thoughts appreciated.
Thanks,
Max
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 a Multigeometry in KML but when I assign a name to the placemark, both points in my placemark have the same name. Is there any possibility to have different names for points in any placemark?
Here is an example of my code:
<Placemark>
<name>TEST</name>
<description></description>
<visibility>1</visibility>
<tessellate>1</tessellate>
<styleUrl>#StyTEST</styleUrl>
<MultiGeometry>
<Point>
<coordinates>-3.6655,40.4364</coordinates>
</Point>
<Point>
<coordinates>-3.6726,40.4308</coordinates>
</Point>
<LineString>
<tessellate>1</tessellate>
<coordinates>
-3.6655,40.4364
-3.6726,40.4308
</coordinates>
</LineString>
</MultiGeometry>
</Placemark>
KML does not allow multiple names/labels for geometries within a single Feature even using a Multi-geometry. If you have multiple points in a MultiGeometry then the same name of the feature will appear over all points. One Placemark point == one label so if you want different labels on map using KML then must have two Placemarks one at each end of the line.
Simple solution is to structure your KML with multiple Placemarks which you can hide in a Document/Folder using the checkHideChildren listItemType. Then it appears in the Places panel in Google Earth as a single "feature" but multiple name labels display on the map as you want. The trick here is that the Folder name appears in the Places Panel and the Placemark names appear as labels on the map.
The following example illustrates such a KML file.
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Example</name>
<open>1</open>
<Style id="hide">
<ListStyle>
<listItemType>checkHideChildren</listItemType>
</ListStyle>
</Style>
<Folder>
<name>TEST1</name>
<styleUrl>#hide</styleUrl>
<Placemark>
<name>TEST1</name>
<MultiGeometry>
<Point>
<coordinates>-3.6726,40.4308</coordinates>
</Point>
<LineString>
<tessellate>1</tessellate>
<coordinates>
-3.6655,40.4364
-3.6726,40.4308
</coordinates>
</LineString>
</MultiGeometry>
</Placemark>
<Placemark>
<name>TEST2</name>
<Point>
<coordinates>-3.6655,40.4364</coordinates>
</Point>
</Placemark>
</Folder>
</Document>
</kml>
A Placemark has only one name. If you need to have each Point have its own name, they need to be separate Placemarks.
From the referenced documentation:
<Placemark>
Syntax
<Placemark id="ID">
<!-- inherited from Feature element -->
<name>...</name> <!-- string -->
<visibility>1</visibility> <!-- boolean -->
<open>0</open> <!-- boolean -->
<atom:author>...<atom:author> <!-- xmlns:atom -->
<atom:link href=" "/> <!-- xmlns:atom -->
<address>...</address> <!-- string -->
<xal:AddressDetails>...</xal:AddressDetails> <!-- xmlns:xal -->
<phoneNumber>...</phoneNumber> <!-- string -->
<Snippet maxLines="2">...</Snippet> <!-- string -->
<description>...</description> <!-- string -->
<AbstractView>...</AbstractView> <!-- Camera or LookAt -->
<TimePrimitive>...</TimePrimitive>
<styleUrl>...</styleUrl> <!-- anyURI -->
<StyleSelector>...</StyleSelector>
<Region>...</Region>
<Metadata>...</Metadata> <!-- deprecated in KML 2.2 -->
<ExtendedData>...</ExtendedData> <!-- new in KML 2.2 -->
<!-- specific to Placemark element -->
<Geometry>...</Geometry>
</Placemark>
A user can't see 40,000 placemarks at once. Take a look at some of the provided Earth Gallery pages like FlightWise (http://mw1.google.com/mw-weather/flightwise/pointer.kml) to see how they use NetworkLink, Region, and Lod tags to split up their data set and present the correct data to the correct view at the correct time.