<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/google-earth/</id>
  <link href="https://www.endpointdev.com/blog/tags/google-earth/"/>
  <link href="https://www.endpointdev.com/blog/tags/google-earth/" rel="self"/>
  <updated>2025-06-13T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>New Cesium KML-CZML Editor Features: Custom Data &amp; Styling, Google 3D Tiles, and More</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2025/06/new-czml-kml-editor-features/"/>
      <id>https://www.endpointdev.com/blog/2025/06/new-czml-kml-editor-features/</id>
      <published>2025-06-13T00:00:00+00:00</published>
      <author>
        <name>Dmitry Kiselev</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2025/06/new-czml-kml-editor-features/banner.webp&#34; alt=&#34;To the right, a satellite imagery map with blue and red gradient polygons drawn over it. To the left, controls for an app, including import/export, create entities, and a list of entities.&#34;&gt;&lt;/p&gt;
&lt;p&gt;I have made some updates to the &lt;a href=&#34;https://www.visionport.com/cesium-kml-czml-editor/&#34;&gt;Cesium KML-CZML editor&lt;/a&gt; I created and maintain.&lt;/p&gt;
&lt;p&gt;The most important additions and changes are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for Google 3D tiles&lt;/li&gt;
&lt;li&gt;Support for writing many more features, including interpolation and time series data for some properties. There are still no editing capabilities for these properties, but while previously the editor would strip these values from the data, it will now copy them into the output file.&lt;/li&gt;
&lt;li&gt;Export to KML and KMZ&lt;/li&gt;
&lt;li&gt;Support for custom data and styling using that custom data&lt;/li&gt;
&lt;li&gt;Switched frontend framework from Vue to React&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adding support for Google 3D tiles is what caused me to create this major version update. In a nutshell, Cesium has its own way of adding reactivity to Entities and Vue doesn&amp;rsquo;t always play nice with it. If I add Google 3D tiles to the scene, it looks like that Cesium Entities have some references to the scene and that causes Vue to apply reactive getters and setters to the whole scene.&lt;/p&gt;
&lt;p&gt;So, I&amp;rsquo;ve switched to using React because it&amp;rsquo;s easier to control which parts should be reactive, as well as when and how you update Cesium Entities and UI components.&lt;/p&gt;
&lt;p&gt;The next important piece is the CZML exporter. The main issue here is that I don&amp;rsquo;t want to strip away features even if I don&amp;rsquo;t support editing them.&lt;/p&gt;
&lt;p&gt;Even if I don&amp;rsquo;t have the UI to edit certain properties or animations for properties, a user can load a CZML document with a mixture of supported and unsupported features without losing the unsupported features. That means that the exporter should be more robust and feature complete than editor itself.&lt;/p&gt;
&lt;p&gt;I will probably separate the exporter as standalone package because it is valuable on its own — I couldn&amp;rsquo;t find a way to export Cesium entities as CZML within the library.&lt;/p&gt;
&lt;h3 id=&#34;custom-data--styling&#34;&gt;Custom data &amp;amp; styling&lt;/h3&gt;
&lt;p&gt;This part is my favorite. I have some experience creating maps, and when you are working with maps you are not focused on polygons or billboards, you are focused on the data, while graphics are just a tool to represent it.&lt;/p&gt;
&lt;p&gt;The previous iteration of the KML-CZML editor was more oriented toward importing KML and massaging it to have the same look in Cesium as it would in Google Earth. That puts focus on graphical features. This time I wanted to make it easy to edit data and style things based on the data.&lt;/p&gt;
&lt;h4 id=&#34;demo&#34;&gt;Demo&lt;/h4&gt;
&lt;p&gt;We&amp;rsquo;ll load in some demo data from New York elections in &lt;code&gt;Mike4326.geojson&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2025/06/new-czml-kml-editor-features/map-with-geojson.webp&#34; alt=&#34;The CZML editor with all yellow polygons drawn over a region of New York&#34;&gt;&lt;/p&gt;
&lt;p&gt;From here, we&amp;rsquo;ll click on the &amp;ldquo;Data table &amp;amp; Conditional Styling&amp;rdquo; button. Then, in the menu that opens, we&amp;rsquo;ll set up Color by value so that we can display different regions differently by our selected attribute. Note the &amp;ldquo;Mike_prc&amp;rdquo; column which displays a percent value. The app will select a color from the gradient based on this value.The app will select a color from the gradient based on this value.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2025/06/new-czml-kml-editor-features/color-by-value-selecting-Mike_prc.webp&#34; alt=&#34;The editor with a full screen popup reading &amp;ldquo;conditional styling&amp;rdquo;. There are three main tabs, &amp;ldquo;Color by value&amp;rdquo;, &amp;ldquo;Labels&amp;rdquo;, and &amp;ldquo;Extrusion and scale&amp;rdquo;. The first is selected. Under the tabs it reads &amp;ldquo;Set entities colors by value of an attribute&amp;rdquo;. Under a dropdown reading &amp;ldquo;Attribute&amp;rdquo;, &amp;ldquo;Mike_prc&amp;rdquo; is selected. A blue to red gradient is below, with a continuous range of colors. At the bottom is a table with polygon 1, polygon 2, etc. Then a style column, all of which have a yellow box. The rightmost column is &amp;ldquo;Mike_prc&amp;rdquo;, and reads a percent number from 0 to 100.&#34;&gt;&lt;/p&gt;
&lt;p&gt;To group values together, we&amp;rsquo;ll toggle the &amp;ldquo;Fixed gradations&amp;rdquo; switch. Then hit the &amp;ldquo;Preview&amp;rdquo; button. By default, there are 9 gradations.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2025/06/new-czml-kml-editor-features/fixed-gradations-9-preview.webp&#34; alt=&#34;The same view, with the gradient now reduced to only 9 values. There is an additional column next to &amp;ldquo;style&amp;rdquo; which shows colors from the gradient corresponding to the Mike_prc value.&#34;&gt;&lt;/p&gt;
&lt;p&gt;We want fewer gradations than that. Let&amp;rsquo;s try out 6.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2025/06/new-czml-kml-editor-features/fixed-gradations-6-preview.webp&#34; alt=&#34;The same view, but now there are only 6 values in the gradient. Most of the preview colors are the same, but a few have been changed to match the 6 values.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Not much difference, but we&amp;rsquo;ll go with the 6 gradations. I&amp;rsquo;ll hit apply, and you can see the colors are now displayed in the &amp;ldquo;Style&amp;rdquo; column, while the &amp;ldquo;Preview&amp;rdquo; column has been hidden.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2025/06/new-czml-kml-editor-features/fixed-gradations-6-applied.webp&#34; alt=&#34;The same view, but now the red to blue colors appear in the &amp;ldquo;style&amp;rdquo; column, and the &amp;ldquo;preview column is hidden.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see how it looks on the map.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2025/06/new-czml-kml-editor-features/map-with-6-gradations.webp&#34; alt=&#34;The original view of the CZML editor. The electoral districts now show a gradient from blue to red, corresponding to the polygon styling we saw, rather than all being yellow as it started.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Very nice! Now let&amp;rsquo;s add some labels for a different attribute, the election district.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2025/06/new-czml-kml-editor-features/label-Election_D-selected.webp&#34; alt=&#34;The conditional styling menu, this time in the &amp;ldquo;Labels&amp;rdquo; tab. Text reads &amp;ldquo;Set Labels and Label text using entities attribute value. The selected attribute is &amp;ldquo;Election_D&amp;rdquo;. There is a box displaying pure black color above the table of polygons.&#34;&gt;&lt;/p&gt;
&lt;p&gt;You can see the text color defaults to black, which won&amp;rsquo;t read well on our colored districts. Let&amp;rsquo;s change it by hitting the &amp;ldquo;edit&amp;rdquo; button next to the color.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2025/06/new-czml-kml-editor-features/label-color-selected.webp&#34; alt=&#34;The same screen, now with added color sliders next to the color square. The color has been changed to a near-white gray.&#34;&gt;&lt;/p&gt;
&lt;p&gt;I changed it to a light gray. Let&amp;rsquo;s look at the map now.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2025/06/new-czml-kml-editor-features/map-with-labels.webp&#34; alt=&#34;A closer view of the map with the red-blue colored districts, now with many light gray labels displaying the name of the election district.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Lots of labels! This is quite a dense area, so you would probably want to zoom in further to see the labels more clearly.&lt;/p&gt;
&lt;p&gt;See my previous blog post &lt;a href=&#34;/blog/2020/12/cesium-kml-czml-editor/&#34;&gt;introducing the Cesium CZML-KML Editor&lt;/a&gt; for more about the Cesium CZML-KML editor.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Exploring Geodatabase Files</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2024/08/exploring-geodatabase-files/"/>
      <id>https://www.endpointdev.com/blog/2024/08/exploring-geodatabase-files/</id>
      <published>2024-08-14T00:00:00+00:00</published>
      <author>
        <name>Constante “Tino” Gonzalez</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2024/08/exploring-geodatabase-files/banner.webp&#34; alt=&#34;The sun shines brightly behind a cloud, casting a half halo of rays to the left of the image, and leaving the right of the image quite dim.&#34;&gt;&lt;/p&gt;
&lt;!-- Image by Jaxson Baerg --&gt;
&lt;p&gt;One of our clients recently provided us with a dataset of real estate properties that they manage, and asked us to generate content based off of the points and polygons in the dataset.&lt;/p&gt;
&lt;p&gt;We will walk through the process of extracting polygons, placemarks, and other info from a geodatabase file and converting them into separate KML files using the &lt;code&gt;ogr2ogr&lt;/code&gt; command-line tool, adding some logic to the data selection to limit the subset of features. We will also explore the GDB file using the GDAL Python library to export the data as JSON for use in other scripts.&lt;/p&gt;
&lt;h3 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic understanding of geospatial data&lt;/li&gt;
&lt;li&gt;Installed versions of the &lt;code&gt;GDAL/OGR&lt;/code&gt; library&lt;/li&gt;
&lt;li&gt;A geodatabase file (&lt;code&gt;.gdb&lt;/code&gt;, &lt;code&gt;.gdb.zip&lt;/code&gt;, or &lt;code&gt;.shp&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;a-first-look-into-the-contents-of-the-gdb-file&#34;&gt;A first look into the contents of the GDB file&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2024/08/exploring-geodatabase-files/pin_label_polygon.webp&#34; alt=&#34;Google earth showing a campus of several buildings, surrounded by a yellow rectangle overlay, and with a blue pin labeled &amp;ldquo;label&amp;rdquo; on one side.&#34;&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ogrinfo example.gdb.zip&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command will list all layers that are available in the dataset. Add a specific layer as a parameter to the same command, and it will output all the fields, their types, and values for every feature in the layer.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ogrinfo example.gdb.zip a_layer_name&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The parameter &lt;code&gt;-so&lt;/code&gt; can be used to omit the values from the output and get only the layer field names and types:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#$&amp;gt; ogrinfo example.gdb.zip Land_Points -so
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INFO: Open of `example.gdb.zip&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      using driver `OpenFileGDB&amp;#39; successful.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Layer name: Land_Points
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Geometry: Point
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feature Count: 219
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Extent: (-122.699891, -23.590280) - (139.763352, 59.622821)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Layer SRS WKT:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GEOGCRS[&amp;#34;WGS 84&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    DATUM[&amp;#34;World Geodetic System 1984&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ELLIPSOID[&amp;#34;WGS 84&amp;#34;,6378137,298.257223563,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            LENGTHUNIT[&amp;#34;metre&amp;#34;,1]]],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PRIMEM[&amp;#34;Greenwich&amp;#34;,0,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ANGLEUNIT[&amp;#34;degree&amp;#34;,0.0174532925199433]],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CS[ellipsoidal,2],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        AXIS[&amp;#34;geodetic latitude (Lat)&amp;#34;,north,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ORDER[2],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ANGLEUNIT[&amp;#34;degree&amp;#34;,0.0174532925199433]],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    USAGE[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        SCOPE[&amp;#34;unknown&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        AREA[&amp;#34;World&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        BBOX[-90,-180,90,180]],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ID[&amp;#34;EPSG&amp;#34;,4326]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Data axis to CRS axis mapping: 2,1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FID Column = OBJECTID
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Geometry Column = Shape
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;asset_type: Integer (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;asset_id: String (15.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;property_code: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;full_address_text: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_name: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_address1: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_city: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_sate_code: String (50.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_postal_code: String (10.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_country_code: String (50.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;division_name: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;region_name: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;market_name: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;submarket_name: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;supplemental_portfolio_name: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ownership_name: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_held_for_sale_acre: Real (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_held_for_sale_hect: Real (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_held_for_development_acre: Real (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_held_for_development_hect: Real (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total_land_acre: Real (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total_land_hectare: Real (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;buildable_area_sf: Real (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;buildable_area_sm: Real (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;buildable_area_tsubo: Real (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_latitude: Real (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;land_longitude: Real (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;geocoded: Integer (0.0) DEFAULT 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;globalid: String (0.0) NOT NULL
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;created_user: String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;created_date: DateTime (0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;last_edited_user:  String (255.0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;last_edited_date: DateTime (0.0)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command shows you information for a single layer, which can be helpful if you are only looking for certain values. However, the geographic data is not much to look at in the terminal. To visualize it, we can convert the data to KML, which applications like Google Earth or Cesium can render while keeping the information as text that can be read:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ogr2ogr -f &amp;#34;KML&amp;#34; example_output.kml example.gdb.zip layer_name&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-f &amp;quot;KML&amp;quot;&lt;/code&gt; specifies the output format&lt;/li&gt;
&lt;li&gt;&lt;code&gt;example_output.kml&lt;/code&gt; is the name of the output KML file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;example.gdb.zip&lt;/code&gt; is the path to the geodatabase file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;layer_name&lt;/code&gt; is the geodatabase layer to export&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This command will export into a KML file:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All the geometries in the layer, be it placemarks or polygons in our case&lt;/li&gt;
&lt;li&gt;All the other fields of information as extended data, which will show up for each feature as a balloon table when visualized in Google Earth&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2024/08/exploring-geodatabase-files/full_label.webp&#34; alt=&#34;Google earth, with a pin selected. A popup dialog displays a table with Land_Points:asset_type, Land_Points:asset_id, and other Land_Points data.&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;the-ogr2ogr--sql-option&#34;&gt;The &lt;code&gt;ogr2ogr&lt;/code&gt; &lt;code&gt;-sql&lt;/code&gt; option&lt;/h3&gt;
&lt;p&gt;The default balloon popup was not the outcome we wanted for this KML file. We first used &lt;code&gt;sed&lt;/code&gt; to remove all the extended data from the KML files, but after looking into it a bit further, we found an &lt;code&gt;ogr2ogr&lt;/code&gt; option, &lt;code&gt;-sql&lt;/code&gt;, that made the data filtering easier. This option lets us add a query to the command just like getting the data from a SQL database.&lt;/p&gt;
&lt;h4 id=&#34;1-extract-property-names&#34;&gt;1. Extract property names&lt;/h4&gt;
&lt;p&gt;To create a KML file with just the names of the properties, look up the layers and fields in them using &lt;code&gt;ogrinfo&lt;/code&gt; and find the points layer that has the names—in this case, &lt;code&gt;Layer_Points&lt;/code&gt;. Then, add the desired SQL query to the command.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ogr2ogr -f &amp;#34;KML&amp;#34; output_names.kml example.gdb.zip -sql &amp;#34;SELECT name FROM Layer_Points&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;2-extract-polygons-only&#34;&gt;2. Extract polygons only&lt;/h4&gt;
&lt;p&gt;The polygon geometries are stored in &lt;code&gt;Layer_Polygons&lt;/code&gt;. They can be selected using the special OGR field &lt;code&gt;OGR_GEOMETRY&lt;/code&gt; that refers to the geometry of the selected layer:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ogr2ogr -f &amp;#34;KML&amp;#34; output_polygons.kml example.gdb.zip -sql &amp;#34;SELECT OGR_GEOMETRY FROM Layer_Polygons&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&#34;/blog/2024/08/exploring-geodatabase-files/polygons_only.webp&#34; alt=&#34;Google Earth, with two irregularly shaped red outlines. One has a popup dialog with a table reading &amp;ldquo;Land_Polygons:OGR_GEOMETRY&amp;rdquo;, and a value of &amp;ldquo;MULTIPOLYGON&amp;rdquo;&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;3-create-kml-with-pins-and-names&#34;&gt;3. Create KML with pins and names&lt;/h4&gt;
&lt;p&gt;To create a KML file with property names as placemarks with pins, we just select the name. The point placemark seems to be included with all data:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ogr2ogr -f &amp;#34;KML&amp;#34; output_pins.kml input.gdb layer_name -sql &amp;#34;SELECT name FROM layer_name&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;4-create-kml-with-pins-only-no-names&#34;&gt;4. Create KML with pins only, no names&lt;/h4&gt;
&lt;p&gt;To get the points with nothing else, we use the SQLite &lt;code&gt;MakePoint&lt;/code&gt; function, which selects a list of points from the KML.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ogr2ogr -f &amp;#34;KML&amp;#34; output_pins.kml input.gdb layer_name -dialect SQLite -sql &amp;#34;SELECT MakePoint(land_longitude, land_latitude) AS geom FROM Land_Points&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;5-extract-limited-properties&#34;&gt;5. Extract limited properties&lt;/h4&gt;
&lt;p&gt;For extracting a limited number of properties, we can add the &lt;code&gt;WHERE&lt;/code&gt; clause to the SQL command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ogr2ogr -f &amp;#34;KML&amp;#34; output_pins.kml input.gdb layer_name -sql &amp;#34;SELECT name FROM layer_name&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can also use the &lt;code&gt;ogr2ogr&lt;/code&gt; &lt;code&gt;-where&lt;/code&gt; flag to use that part of the query only:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ogr2ogr -f &amp;#34;KML&amp;#34; limited_output_polygons.kml input.gdb layer_name -where &amp;#34;ID IN (1, 2, 3)&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;6-run-it-all-in-a-python-script&#34;&gt;6. Run it all in a Python script&lt;/h4&gt;
&lt;p&gt;There is a Python GDAL library, which I will cover the basics of later, but first, here is a simplified example using Python &lt;code&gt;subprocess&lt;/code&gt; to run the ogr2ogr commands we tested in the terminal.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;subprocess&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gdb_file = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;example.gdb.zip&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;column_name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;p_code&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;elem_str = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#39;a1&amp;#39;, &amp;#39;a2&amp;#39;, &amp;#39;b1&amp;#39;, &amp;#39;b3&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sql_land_labels = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;SELECT land_name FROM Land_Points WHERE &lt;/span&gt;&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;{&lt;/span&gt;column_name&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt; IN (&lt;/span&gt;&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;{&lt;/span&gt;elem_str&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subprocess.run([&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;ogr2ogr&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-f&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;KML&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;land_labels.kml&amp;#39;&lt;/span&gt;, gdb_file, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-sql&amp;#39;&lt;/span&gt;, sql_land_labels])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sql_land_points = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;SELECT MakePoint(land_longitude, land_latitude) AS geom FROM Land_Points WHERE &lt;/span&gt;&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;{&lt;/span&gt;column_name&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt; IN (&lt;/span&gt;&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;{&lt;/span&gt;elem_str&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subprocess.run([&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;ogr2ogr&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-f&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;KML&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;land_points.kml&amp;#39;&lt;/span&gt;, gdb_file, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-dialect&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;SQLite&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-sql&amp;#39;&lt;/span&gt;, sql_land_points])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sql_land_polygons = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;SELECT OGR_GEOMETRY FROM Land_Polygons WHERE &lt;/span&gt;&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;{&lt;/span&gt;column_name&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt; IN (&lt;/span&gt;&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;{&lt;/span&gt;elem_str&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subprocess.run([&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;ogr2ogr&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-f&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;KML&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;land_pols.kml&amp;#39;&lt;/span&gt;, gdb_file, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-sql&amp;#39;&lt;/span&gt;, sql_land_polygons])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This script will create the three different KML files that we usually need for our presentations. We used variables for the &lt;code&gt;gdb_file&lt;/code&gt;, &lt;code&gt;column_name&lt;/code&gt;, and &lt;code&gt;elem_str&lt;/code&gt; command line parameters to make the script easy to use for selecting other data. We also use them in other scripts to join, apply custom styling, and add regions to the KMLs, which will be covered in another blog post.&lt;/p&gt;
&lt;h4 id=&#34;7-extract-all-data-as-json-from-one-layer-using-the-python-gdal-library&#34;&gt;7. Extract all data as JSON from one layer using the Python GDAL library&lt;/h4&gt;
&lt;p&gt;I probably should have started here, but I only used the Python library later on in the process to join the &lt;code&gt;gdp.zip&lt;/code&gt; file data with data from other sources (spreadsheets, emails, etc.).&lt;/p&gt;
&lt;p&gt;First, install the GDAL library:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install gdal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then you can use the following Python script, changing as necessary the &lt;code&gt;gdb_file&lt;/code&gt;, &lt;code&gt;layer_name&lt;/code&gt;, and the unique field chosen to structure the data. The code is explained in the comments.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;#!/bin/python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;osgeo&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; ogr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Open the Geodatabase file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;driver = ogr.GetDriverByName(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;OpenFileGDB&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gdb_file = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;example.gdb.zip&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;data_source = driver.Open(gdb_file, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Get the layer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;layer_name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;Building_Points&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;layer = data_source.GetLayerByName(layer_name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; layer:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# Get the layer definition&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    layer_defn = layer.GetLayerDefn()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# Get the number of fields in the layer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    num_fields = layer_defn.GetFieldCount()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# Initialize an empty list to store field names&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    field_names = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# Iterate over each field and add its name to the list&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;range&lt;/span&gt;(num_fields):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        field_defn = layer_defn.GetFieldDefn(i)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        field_name = field_defn.GetName()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        field_names.append(field_name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Field names:&amp;#34;&lt;/span&gt;, field_names)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Layer &amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;{&lt;/span&gt;layer_name&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39; not found.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;all_info = {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Iterate over all features and organize all field names under a unique one for the dictionary structure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; feature &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; layer:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; feature &lt;span style=&#34;color:#080&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#080&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        globalid = feature.GetField(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;globalid&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        all_info[globalid] = {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; fn &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; field_names:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            all_info[globalid][fn] = feature.GetField(fn)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Close the data source&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;data_source = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Save information to a JSON file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;output_file = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;info.json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;open&lt;/span&gt;(output_file, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;as&lt;/span&gt; json_file:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    json.dump(all_info, json_file, indent=&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Information saved to &lt;/span&gt;&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;{&lt;/span&gt;output_file&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The script will create a JSON file with all the information on the layer.&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Following these steps, we can efficiently manage and visualize geospatial data using &lt;code&gt;ogr2ogr&lt;/code&gt;, SQL, and KML, and in some cases, JSON. These methods allow for a high degree of customization and can be tailored to specific project requirements.&lt;/p&gt;
&lt;h3 id=&#34;additional-resources&#34;&gt;Additional Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gdal.org&#34;&gt;GDAL/OGR Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gdal.org/python/&#34;&gt;GDAL Python Bindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developers.google.com/kml/documentation&#34;&gt;KML Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sqlite.org/docs.html&#34;&gt;SQLite Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
    <entry>
      <title>CZML-KML Editor Geometry Editing</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2021/04/czml-kml-editor-geometry-editing/"/>
      <id>https://www.endpointdev.com/blog/2021/04/czml-kml-editor-geometry-editing/</id>
      <published>2021-04-13T00:00:00+00:00</published>
      <author>
        <name>Dmitry Kiselev</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2021/04/czml-kml-editor-geometry-editing/czml-kml-geometry-editing.jpg&#34; alt=&#34;Screenshot of CZML-KML editor showing geometry editing feature&#34;&gt;&lt;/p&gt;
&lt;p&gt;We are happy to introduce a new feature for the Cesium CZML-KML Editor: polygons and polylines geometry editing. You can now edit geometries for existing entities and move entered points during the creation process. Here is a video with a short summary of the editing process:&lt;/p&gt;
&lt;iframe style=&#34;margin-bottom: 1em&#34; width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube-nocookie.com/embed/rLhy35_X5iA&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;See our previous blog post &lt;a href=&#34;/blog/2020/12/cesium-kml-czml-editor/&#34;&gt;introducing the Cesium CZML-KML Editor&lt;/a&gt; for further reference.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Announcing the Cesium KML-CZML Editor</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2020/12/cesium-kml-czml-editor/"/>
      <id>https://www.endpointdev.com/blog/2020/12/cesium-kml-czml-editor/</id>
      <published>2020-12-21T00:00:00+00:00</published>
      <author>
        <name>Dmitry Kiselev</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-00.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;End Point’s immersive technology team is happy to present a great new tool for the rapidly growing Cesium community: &lt;a href=&#34;https://www.visionport.com/cesium-kml-czml-editor/&#34;&gt;Cesium KML-CZML Editor&lt;/a&gt;. The editor gives users the ability to visually and dynamically edit KML and CZML in its Cesium browser window. Updates made with it can be exported at any time to CZML, the native markup language for Cesium.&lt;/p&gt;
&lt;p&gt;The Cesium KML-CZML Editor addresses an important but hitherto unaddressed need of the Cesium community: It provides an intuitive interface for making adjustments to fix the many inconsistencies with how KML created for (and often by) Google Earth appears on 3D maps rendered with Cesium. It is a powerful tool for converting and adapting KML for Google Earth into CZML that displays nicely in Cesium. The editor also works as a visual editor for creating and editing CZML, regardless of whether you’re converting from KML.&lt;/p&gt;
&lt;p&gt;The inconsistencies with how Cesium displays KML created for Google Earth are due to occasional differences between how Cesium and Google Earth render KML when various attributes aren’t specifically set within a given instance of code. The situation is similar to how web browsers sometimes interpret given instances of HTML differently. Just as with HTML, KML doesn’t require every attribute to be defined in a given instance of markup code.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-01.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;On the left side we have the editor toolbar, and on the right side the Cesium globe showing loaded or created entities the way they would appear in Cesium.&lt;/p&gt;
&lt;p&gt;The Editor Toolbar consist of the following areas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File Import: you can load KML, KMZ, CZML and GeoJSON formatted data, and you can load multiple files to combine them into one CZML document.&lt;/li&gt;
&lt;li&gt;Creation tools.&lt;/li&gt;
&lt;li&gt;A list of uploaded or created entities (will appear after upload or creation of a new entity).&lt;/li&gt;
&lt;li&gt;The actual editor for entity properties (will appear after entity selection).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s start with a very basic example of highlighting a building by marking it with a pin in Google Earth:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-02.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now let’s move the camera about in different ways, especially noticing how the pin appears when zooming in and out. The pin stays close to the top of the building.&lt;/p&gt;
&lt;video controls&gt;
  &lt;source src=&#34;/blog/2020/12/cesium-kml-czml-editor/video-0.webm&#34; type=&#34;video/webm&#34;&gt;
  Sorry, your browser doesn’t support embedded videos.
&lt;/video&gt;
&lt;p&gt;Then let’s open the same KML in Cesium with a 3D building tileset loaded, to compare apples to apples:&lt;/p&gt;
&lt;video controls&gt;
  &lt;source src=&#34;/blog/2020/12/cesium-kml-czml-editor/video-1.webm&#34; type=&#34;video/webm&#34;&gt;
  Sorry, your browser doesn’t support embedded videos.
&lt;/video&gt;
&lt;p&gt;It’s easy to see that the green frame which is placed around the geographic position stays around the building, but the icon point of rotation in Cesium doesn’t match the one in Google Earth and the pin falls through the roof and lifts up unfortunately high above the building.&lt;/p&gt;
&lt;p&gt;KML doesn’t enforce certain aspects of its representation. If certain attributes are not specified or can’t be implemented exactly, then the KML browsers have the freedom to set different default values for them.&lt;/p&gt;
&lt;p&gt;In this example, Cesium and Google Earth display different pixel offsets for the pin icon, because in KML the offset is specified as a ratio of the image, but Cesium specifies the offset in pixels. Cesium converts the pixel offset of the pin from the ratio specified, but with some errors. Cesium reverses the X axis, and in some cases Cesium also calculates the pin icon image size incorrectly. So here it calculates the X offset as -4, which moves the pin icon to the left. To fix that, we can reverse the X axis back to 4 or even move the pin icon 8 pixels further to the right.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-03.jpg&#34; alt=&#34;&#34;&gt;
🡆
&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-04.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;The next issue is how the Z coordinate (altitude) is interpreted. Is it above sea level, above land according to some averaged model of the land, or on the land directly below a point?&lt;/p&gt;
&lt;p&gt;Note that 3D tilesets in Cesium are absolutely positioned. This means that if you show 3D buildings and want your pin to stick to a building, it’s better to use absolute elevation. Hence, it makes sense to set Height Reference to &lt;code&gt;NONE&lt;/code&gt;, which will force Cesium to use the absolute pin position.&lt;/p&gt;
&lt;p&gt;Another option in cases like this is to use relative elevation. This can be helpful if you don’t use 3D tiles, but instead use 3D terrain data, for example, with Cesium World Terrain or Maptiler. It’s especially helpful if you will be switching 3D terrain on and off. In this case, a relatively positioned pin will follow the elevation regardless of whether 3D terrain is turned on or off.&lt;/p&gt;
&lt;p&gt;To set it up, adjust Altitude and set Height Reference to &lt;code&gt;RELATIVE_TO_GROUND&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-05.jpg&#34; alt=&#34;&#34;&gt;
&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-06.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Here are the results for both options:&lt;/p&gt;
&lt;video controls&gt;
  &lt;source src=&#34;/blog/2020/12/cesium-kml-czml-editor/video-2.webm&#34; type=&#34;video/webm&#34;&gt;
  Sorry, your browser doesn’t support embedded videos.
&lt;/video&gt;
&lt;p&gt;As you can see, now we have the pin-point of the marker stuck to the desired location.&lt;/p&gt;
&lt;p&gt;These are the basics for how to match pins created in Google Earth with their Cesium representations, but in Cesium there are many more options for rendering pins. You can read the &lt;a href=&#34;https://cesium.com/docs/cesiumjs-ref-doc/BillboardGraphics.html&#34;&gt;relevant Cesium documentation&lt;/a&gt; (in Cesium terminology Pins are called Billboards) or interactively explore a live version of this editor to change color, rotation, translucency by distance, and other properties.&lt;/p&gt;
&lt;p&gt;Now let’s look at a polygon created in KML for Google Earth:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-07.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Then let’s open it in Cesium:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-08.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Well, we can select a polygon, but we don’t see it. This happens because the 3D terrain data covers the polygon. Just changing the Height reference helps, but it’s still not what we want:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-09.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Cesium has some default assumptions about polygons and rectangles and when to clamp them to the ground.&lt;/p&gt;
&lt;p&gt;As commented in the &lt;a href=&#34;https://sandcastle.cesium.com/?src=Clamp%20to%20Terrain.html&#34;&gt;Cesium SandCastle Clamp to Terrain demo code&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Corridors, polygons and rectangles will be clamped automatically if they are filled with a constant color and have no height or extruded height.&lt;/p&gt;
&lt;p&gt;NOTE: Setting height to 0 will disable clamping.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;So to get a polygon actually clamped to ground, we have to delete the Height property, not just set it to 0:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-10.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now let’s add a 3D tileset:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-11.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;And again, this is probably not exactly what you wanted. By default, Cesium doesn’t know what type of 3D tileset you would prefer, or whether you want the polygons to cover the tiles, or the tiles to cover the polygons. If you have a fairly large polygon covering a whole city, and a fairly low resolution 3D tileset, you probably want to highlight the whole area. But in the example above, we want our polygon to stick to the ground but not the buildings.&lt;/p&gt;
&lt;p&gt;Next, let’s use the Classification Type field, setting it to “TERRAIN” to select what the clamped polygon applies to:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-12.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now, let’s open some exported data. Here’s a typical set of exported points generated with geojson.io:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-13.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Let’s choose a point and change its icon and its icon’s vertical alignment (so it doesn’t fall through the terrain) and dimensions:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-14.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Here we have selected one icon and updated its properties to make it appear as we want, but changing all the icons one by one would take forever, especially for large data sets.&lt;/p&gt;
&lt;p&gt;Click “COPY TO OTHER PINS”:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-15.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;On the left is a list with all the entities to which the changed properties are applicable and on the right is the list of the properties that were changed for the model entity selected. By default, all the properties are checked to be copied to applicable entities but in this example we only want to change the vertical alignment for all the pins, but want to keep the icon and icon dimension of the other pins unchanged. So we uncheck the image, width and height properties:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-16.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Below we see how our scene looks after the update is applied. All the pins are above the ground, but the icons and dimensions are not changed:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2020/12/cesium-kml-czml-editor/image-17.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;After you have all the data styled the way you want, download your CZML!&lt;/p&gt;
&lt;p&gt;The Cesium KML-CZML Editor code is Apache 2 licensed. It is &lt;a href=&#34;https://github.com/EndPointCorp/cesium-kml-czml-editor&#34;&gt;available here&lt;/a&gt;.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>The New Earth</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/04/the-new-earth/"/>
      <id>https://www.endpointdev.com/blog/2017/04/the-new-earth/</id>
      <published>2017-04-21T00:00:00+00:00</published>
      <author>
        <name>Dave Jenkins</name>
      </author>
      <content type="html">
        &lt;iframe allowfullscreen=&#34;&#34; frameborder=&#34;0&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/O-XidwKsKAE&#34; width=&#34;560&#34;&gt;&lt;/iframe&gt;
&lt;p&gt;As many of you may have seen, earlier this week Google released a major upgrade to the Google Earth app. Overall, it’s much improved, sharper, and a deeper experience for viewers. We will be upgrading/incorporating our managed fleet of Liquid Galaxies over the next two months after we’ve had a chance to fully test its functionality and polish the integration points, but here are some observations for how we see this updated app impacting the overall Liquid Galaxy experience.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2017/04/the-new-earth/image-0-big.gif&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;113&#34; src=&#34;/blog/2017/04/the-new-earth/image-0.gif&#34; width=&#34;200&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Hooray! The new Earth is here! The New Earth is here! Certainly, this is exciting for us. The Google Earth app plays a key central role in the Liquid Galaxy viewing experience, so a major upgrade like this is a most welcome development. So far, the reception has been positive. We anticipate it will continue to get even better as people really sink their hands into the capabilities and mashup opportunities this browser-based Earth presents.&lt;/p&gt;
&lt;p&gt;We tested some pre-release versions of this application, and successfully integrated them with the Liquid Galaxy and are very happy with how we are able to view-synchronize unique instances of the new Google Earth across displays with appropriate geometrically configured offsets.&lt;/p&gt;
&lt;p&gt;What to look for in this new application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Stability: The new Google Earth runs as a &lt;a href=&#34;https://en.wikipedia.org/wiki/Google_Native_Client&#34;&gt;NaCl&lt;/a&gt; application in a Chrome browser. This is an enormous advance for Google Earth. As an application in Chrome it is instantly accessible to billions of new users with their established expectations. Because the new Google Earth uses Chrome the Google Earth developers will no longer need to engage in the minutiae of having to support multiple desktop operating systems, but now can instead concentrate on the core-functionality of Google Earth and leverage the enormous amount of work that the Chrome browser developers do to make Chrome a cross-platform application.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Smoother 3D: The (older) Google Earth sometimes has a sort of “melted ice cream” look to the 3D buildings in many situations. Often, buildings fail to fully load from certain viewpoints. From what we’re seeing so far, the 3D renderings in the New Earth appear to be a lot sharper and cleaner.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Browser-based possibilities: As focus turns more and more to browser-based apps, and as JavaScript libraries continue to mature, the opportunities and possibilities for how to display various data types, data visualizations, and interactions really start to multiply. We can already see this with the sort of deeper stories and knowledge cards that Google is including in the Google Earth interface. We hope to take the ball and run with it, as the Liquid Galaxy can already handle a host of different media types. We might exploit layers, smart use controls, realtime content integration from other available databases, and&amp;hellip; okay, I’m getting ahead of myself.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2017/04/the-new-earth/image-1-big.png&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;180&#34; src=&#34;/blog/2017/04/the-new-earth/image-1.png&#34; width=&#34;320&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;The New Google Earth makes a major point of featuring stories and deeper contextual information, rather than just ogling at the terrain: as pretty as the Grand Canyon is to look at, knowing a little about the explorers, trails, and history makes it such a nicer experience to view. We’ve gone through the same evolution with the Liquid Galaxy: it used to be just a big Google Earth viewer, but we quickly realized the need for more context and usable information for a richer interaction with the viewers by combining Earth with street view, panoramic video, 3D objects, etc. It’s why we built a content management system to create presentations with scenes. We anticipate that the knowledge cards and deeper information that Google is integrating here will only strengthen that interaction.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2017/04/the-new-earth/image-2-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;150&#34; src=&#34;/blog/2017/04/the-new-earth/image-2.jpeg&#34; width=&#34;200&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;We are looking to roll out the new Google Earth to the fleet in the next couple of months. We need to do a lot of testing and then update the Liquid Galaxies with minimal (or no) disturbance to our clients, many of whom rely on the platform as a daily sales and showcasing tool for their businesses. As always, if you have any questions, please reach us directly via email or call.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>ROS Platform Upgrades for Liquid Galaxy</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/12/ros-platform-upgrades-for-liquid-galaxy/"/>
      <id>https://www.endpointdev.com/blog/2015/12/ros-platform-upgrades-for-liquid-galaxy/</id>
      <published>2015-12-14T00:00:00+00:00</published>
      <author>
        <name>Dave Jenkins</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2015/12/ros-platform-upgrades-for-liquid-galaxy/image-0-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2015/12/ros-platform-upgrades-for-liquid-galaxy/image-0.jpeg&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;For the last few months, End Point has been rolling out a new application framework along with updated display applications and monitoring infrastructure for the Liquid Galaxy Display Platform.  These upgrades center on the ROS framework and allow a great number of functionality extensions and enhancements for the end user, as well as improvements to the stability and security of the core systems. It is intended that the 50+ systems that we currently maintain and support on behalf of our enterprise clients will be upgraded to this new platform.&lt;/p&gt;
&lt;h3 id=&#34;ros-overview&#34;&gt;ROS Overview&lt;/h3&gt;
&lt;p&gt;ROS is short for “Robot Operating System”.  Just as it sounds, it is a framework used for controlling robots, and handles various environmental ‘inputs’ and ‘outputs’ well.  End Point chose this framework in conjunction with related ongoing development projects on behalf of our enterprise clients.  This system allows complex interactions from a touchscreen, camera, SpaceNav, or other device to be interpreted conditionally and then invoke other outputs such as displaying Google Earth, Street View, or other content on a given screen, speaker, or other output device.  For more details, see: &lt;a href=&#34;http://www.ros.org&#34;&gt;http://www.ros.org&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2015/12/ros-platform-upgrades-for-liquid-galaxy/image-1-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2015/12/ros-platform-upgrades-for-liquid-galaxy/image-1.jpeg&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3 id=&#34;liquid-galaxy-enhancements&#34;&gt;Liquid Galaxy Enhancements&lt;/h3&gt;
&lt;p&gt;This new platform brings a number of improvements to the back-end systems and viewing customer experience.&lt;/p&gt;
&lt;h4 id=&#34;improved-street-view-panospheres&#34;&gt;Improved Street View Panospheres&lt;/h4&gt;
&lt;p&gt;The new Street View viewer draws Street View tiles inside a WebGL sphere.  This is a dramatic performance and &lt;a href=&#34;https://www.youtube.com/watch?v=YvQ5JmXx3Bg&#34;&gt;visual enhancement&lt;/a&gt; over the older method, and can now support spherical projection, hardware acceleration, and seamless panning.  For a user, this means tilting the view vertically as well as horizontally, zooming in and out, and improved frame rates.&lt;/p&gt;
&lt;h4 id=&#34;improved-panoramic-video&#34;&gt;Improved Panoramic Video&lt;/h4&gt;
&lt;p&gt;As with the panoramic Street View application, this new platform improves the panoramic video playback as well.  YouTube and Google have announced major initiatives to start actively supporting 360° panoramic video, including the financial backing of some high profile projects as  example use cases.  The Liquid Galaxy, with its panoramic screen layout already in place, is ideally suited for this new media format.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2015/12/ros-platform-upgrades-for-liquid-galaxy/image-2-big.png&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2015/12/ros-platform-upgrades-for-liquid-galaxy/image-2.png&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4 id=&#34;improved-touchscreen&#34;&gt;Improved Touchscreen&lt;/h4&gt;
&lt;p&gt;The touchscreen incorporates a templated layout for easier modification and customization.  The scene view selector is now consolidated to a single interface and no longer requires sub-pages or redundant touches.  The Street View interface, complete with the ‘pegman’ icon, is a photo-realistic map with pinch and zoom just like a tablet interface.&lt;/p&gt;
&lt;h4 id=&#34;browser-windows&#34;&gt;Browser Windows&lt;/h4&gt;
&lt;p&gt;The Liquid Galaxy can control multiple browser windows that can appear anywhere on the screens, often across multiple screens.  These browser windows can show anything that can appear in a desktop web browser: web pages, videos, social media updates, data visualizations, etc.&lt;/p&gt;
&lt;h4 id=&#34;content-management-system&#34;&gt;Content Management System&lt;/h4&gt;
&lt;p&gt;Beginning in 2014, End Point began to upgrade the content management system for the Liquid Galaxy.  With the new ROS platform, we have updated this application to Roscoe (the ROS content experience).  Roscoe gives registered users the ability to create complex presentations with specific scenes.  Each scene can have a specific global location to guide the Google Earth or Street View, and then invoke overlays that appear across the screens.  These overlays can include photos,  data graphs, videos, or web pages.  Each scene can also include a specific KML data set e.g., population density data, property value data, etc.) that can appear as 3D bar graphs directly in the ‘Earth’ view.&lt;/p&gt;
&lt;h4 id=&#34;content-isolation&#34;&gt;Content Isolation&lt;/h4&gt;
&lt;p&gt;Isolating the entire presentation layer in ROS makes it easy to develop exhibits without a full-fledged Liquid Galaxy system.  The entire ROS stack can be installed and run on an Ubuntu 14.04 computer or within a Docker container.  This ROS stack can be used by a developer or designer to build out presentations that will ultimately run on a Liquid Galaxy system.&lt;/p&gt;
&lt;h4 id=&#34;app-modularization&#34;&gt;App Modularization&lt;/h4&gt;
&lt;p&gt;Each component of a Liquid Galaxy exhibit is a configurable ROS node, allowing us to reuse large swaths of code and distribute the exhibit across any number of machines. This architecture brings two strong advantages: 1) each ROS node does one specific thing, which increases portability and modularity, and 2) each node can be tested automatically, which improves reliability.&lt;/p&gt;
&lt;h4 id=&#34;enhanced-platform-stability&#34;&gt;Enhanced Platform Stability&lt;/h4&gt;
&lt;p&gt;By unifying all deployments on a common base, End Point is able to deploy bug fixes, monitoring scripts, and ongoing enhancements much more quickly and safely.  This has enhanced the overall stability for all supported and monitored Liquid Galaxy platforms.&lt;/p&gt;
&lt;h3 id=&#34;product-roadmap&#34;&gt;Product Roadmap&lt;/h3&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2015/12/ros-platform-upgrades-for-liquid-galaxy/image-3-big.png&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2015/12/ros-platform-upgrades-for-liquid-galaxy/image-3.png&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;The items described above are the great things that we can do already with this new platform.  Even greater things are coming soon:&lt;/p&gt;
&lt;h4 id=&#34;lidar-point-clouds&#34;&gt;LiDAR Point Clouds&lt;/h4&gt;
&lt;p&gt;End Point has already built early prototypes for the Liquid Galaxy platform that can view LiDAR point clouds.  LiDAR is rapidly gaining traction in the architecture, surveyor, and construction industries.  With the large viewing area of the Liquid Galaxy, these LiDAR point clouds become much more impactful and useful to the command and control center.&lt;/p&gt;
&lt;h4 id=&#34;google-earth-and-google-maps-upgrades&#34;&gt;Google Earth and Google Maps Upgrades&lt;/h4&gt;
&lt;p&gt;End Point continues to work with the latest developments in the Google Earth and Google Maps platforms and is actively working to integrate new features and functionality. These new capabilities will be rolled out to the fleet of Liquid Galaxies as available.&lt;/p&gt;
&lt;h4 id=&#34;3d-webgl-visualizations&#34;&gt;3D WebGL Visualizations&lt;/h4&gt;
&lt;p&gt;The Liquid Galaxy will be enhanced to view completely virtual 3D environments using WebGL and other common formats.  These environments include complex data visualizations, interior space renderings for office planning, and even games.&lt;/p&gt;
&lt;h3 id=&#34;next-steps&#34;&gt;Next Steps&lt;/h3&gt;
&lt;p&gt;If you’re considering the Liquid Galaxy platform, &lt;a href=&#34;https://www.visionport.com/contact/&#34;&gt;contact us&lt;/a&gt; to discuss these latest enhancements and how they can improve the communications and presentation tools for your organization.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Non-English Google Earth Layers on the Liquid Galaxy</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/05/non-english-google-earth-layers-on/"/>
      <id>https://www.endpointdev.com/blog/2015/05/non-english-google-earth-layers-on/</id>
      <published>2015-05-12T00:00:00+00:00</published>
      <author>
        <name>Josh Ausborne</name>
      </author>
      <content type="html">
        &lt;p&gt;The availability to activate layers within Google Earth is one of the things that makes Earth so powerful.  In fact, there are many standard layers that are built into Earth, including weather, roads, place names, etc.  There are also some additional layers that have some really interesting information, including one I noticed relatively recently called “Appalachian Mountaintop Removal” which is interesting to me now that I live in Tennessee.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2015/05/non-english-google-earth-layers-on/image-0-big.png&#34; imageanchor=&#34;1&#34; style=&#34;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2015/05/non-english-google-earth-layers-on/image-0.png&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;As you can see, however, that while some of these available layers are interesting on a desktop, they’re not necessarily very visually appealing on a Liquid Galaxy.  We have identified a standard set of layers to enable and disable within Earth so that things don’t appear too cluttered while running.  Some things we’ve disabled by default are the weather and the roads, as well as many levels of place names and boundaries.  For example, we have boundaries of countries and water bodies enabled, but don’t want lines drawn for states, provinces, counties, or other areas such as those.&lt;/p&gt;
&lt;p&gt;To disable these layers, we modify the GECommonSettings.conf file on the machines that running Earth.  This file has everything pretty well spelled out in a readable manner, and it’s fairly easy to determine what layers you’re enabling or disabling.&lt;/p&gt;
&lt;p&gt;Here’s an example of some of the entries contained within the GECommonSettings.conf file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1st%20Level%20Admin%20Names%20%28States_Provinces%29=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2nd%20Level%20Admin%20Regions%20%28Counties%29=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Islands=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__mw1.google.com_mw-earth-vectordb_geographic_features_en.kml\Geographic%20Features=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Water%20Bodies=true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Places%20=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Panoramio=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;360%20Cities=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Photorealistic%20=true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Trees=true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Populated%20Places=true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Roads=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Gray%20=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__mw1.google.com_mw-weather_base_files_kml_weather_en.kmz\Clouds=true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__mw1.google.com_mw-weather_base_files_kml_weather_en.kmz\Radar=true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__mw1.google.com_mw-weather_base_files_kml_weather_en.kmz\Conditions%20and%20Forecasts=true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__mw1.google.com_mw-weather_base_files_kml_weather_en.kmz\Information=true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__mw1.google.com_mw-earth-vectordb_gallery_layers_gallery_root_en.kmz\360Cities=false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;See, that’s pretty self-explanatory, isn’t it?&lt;/p&gt;
&lt;p&gt;Well, it is until you start introducing other languages to the mix.  For example, we needed to run Earth in Korean language mode for one of our clients.  Once we fired up Earth and specified that the language would be Korean, Earth came up with all of the default layers turned on.  All of those layers that we’d disabled in English Earth stayed on and cluttered the displays with so many icons for each and every layer.&lt;/p&gt;
&lt;p&gt;It took some trial and error, but I was eventually able to figure out what to do to resolve this.  I loaded Google Earth in Korean mode on my Ubuntu VM, made my changes to the selected layers via the Layers selection area within Earth, then quit.  When I looked at the GECommonSettings.conf file after quitting Earth, I found a bunch of new line items added to the file.  It seems that each of the options had new lines, though I couldn’t exactly decipher which lines controlled which options.&lt;/p&gt;
&lt;p&gt;Here’s an example of some of the new entries that are now contained within my GECommonSettings.conf file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__kh.google.com%3A80_\%UAD6D%UACBD=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__kh.google.com%3A80_\%UAD6D%UAC00%UBA85=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__kh.google.com%3A80_\%UD574%UC548%UC120=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__kh.google.com%3A80_\1%UCC28%20%UD589%UC815%20%UACBD%UACC4%UC120%28%UC8FC_%UB3C4%29=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__kh.google.com%3A80_\2%UCC28%20%UD589%UC815%UB2E8%UC704%20%UC9C0%UC5ED%28%UAD70%29=false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__kh.google.com%3A80_\%UC778%UAD6C%UBC00%UC9D1%UC9C0%UC5ED=true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http%3A__kh.google.com%3A80_\%UC12C=false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, I’ll be honest and say that I don’t have clue exactly what %UAD6D%UACBD and 1%UCC28%20%UD589%UC815%20%UACBD%UACC4%UC120%28%UC8FC_%UB3C4%29 mean, but I really don’t have to know.  All I know is that they got disabled when I disabled the undesired layers within Earth.  I then copied these lines to the configuration on my Liquid Galaxy, and the next time I fired it up in Korean, the layers were no longer cluttering up the displays.&lt;/p&gt;
&lt;p&gt;I was able to use this exact same method to determine which layers to enable or disable for one of our Spanish-language clients, as well.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Liquid Galaxy for Google.org at SXSW</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/03/liquid-galaxy-for-googleorg-at-sxsw/"/>
      <id>https://www.endpointdev.com/blog/2015/03/liquid-galaxy-for-googleorg-at-sxsw/</id>
      <published>2015-03-24T00:00:00+00:00</published>
      <author>
        <name>Dave Jenkins</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2015/03/liquid-galaxy-for-googleorg-at-sxsw/image-0-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2015/03/liquid-galaxy-for-googleorg-at-sxsw/image-0.jpeg&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;End Point enjoyed an opportunity to work with Google.org, who bought a Liquid Galaxy to show their great efforts, at last week&amp;rsquo;s SXSW conference in Austin. Google.org has a number of projects worldwide, all focused on how tech can bring about unique and inventive solutions for good. To showcase some of those projects, Google asked us to develop presentations for the Liquid Galaxy where people could fly to a given location, read a brief synopsis of the grantee organizations, and view presentations which included virtual flight animations, map overlays, and videos of the various projects.&lt;/p&gt;
&lt;p&gt;Some of the projects included are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Charity:Water&lt;/strong&gt;—​The charity: water presentation included scenes featuring multi screen video of Scott Harrison (Founder/CEO) and Robert Lee (Director of Special Programs), and an animated virtual tour of charity: water well sites in Ethiopia.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;World Wildlife Fund&lt;/strong&gt;—​The World Wildlife Fund presentation featured a virtual tour of the Bouba N’Djida National Park, Cameroon putting the viewer into the perspective of a drone patrolling the park for poachers. Additional scenes in the presentation revealed pathways of transport for illegal ivory from the park through intermediate stops in Nigeria and Hong Kong before reaching China.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Samasource&lt;/strong&gt;—​The Samasource presentation showed slums where workers start and the technology centers they are able to migrate to while serving a global network of technology clients.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2015/03/liquid-galaxy-for-googleorg-at-sxsw/image-1-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2015/03/liquid-galaxy-for-googleorg-at-sxsw/image-1.jpeg&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;But the work didn’t stop there! Google.org was also sharing the space with the XPrize opening gala on Monday night. For this event, we drew up a simple game where attendees could participate in various events around the room, receive coded answers at each station, and then enter their code into the Liquid Galaxy touchscreen. If successful, the 7-screen display whisked them to the Space Port in the Mojave, then into orbit. If the wrong code was entered, the participant got splashed into the Pacific Ocean. It was great fun!&lt;/p&gt;
&lt;p&gt;The SXSW engagement is the latest in an ongoing campaign to bring attention to global challenges and how Google.org is helping solve those challenges. End Point enjoys a close working relationship with Google and Google.org. We relish the opportunity to bring immersive and inviting displays that convey a wealth of information to viewers in such an entertaining and engrossing manner.&lt;/p&gt;
&lt;p&gt;This event ran for 2 days at the Trinity Hall venue just 1 block from the main SXSW convention center in downtown Austin, Texas.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Kamelopard version 0.0.15 released</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/05/kamelopard-version-0015-released/"/>
      <id>https://www.endpointdev.com/blog/2014/05/kamelopard-version-0015-released/</id>
      <published>2014-05-22T00:00:00+00:00</published>
      <author>
        <name>Josh Tolley</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center; float: left&#34;&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Camelopardalis&#34; imageanchor=&#34;1&#34; style=&#34;clear: left; float: left; margin-bottom: 1em; margin-right: 1em; width: 300px; height: 200px&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;https://upload.wikimedia.org/wikipedia/commons/2/24/Sidney_Hall_-_Urania%27s_Mirror_-_Camelopardalis%2C_Tarandus_and_Custos_Messium.jpg&#34;/&gt;&lt;/a&gt;&lt;p align=&#34;center&#34; style=&#34;width: 300px&#34;&gt;&lt;small&gt;The Camelopardalis constellation, as shown in &lt;a href=&#34;http://www.ianridpath.com/atlases/urania.htm&#34;&gt;Urania’s Mirror&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;I’ve just pushed &lt;a href=&#34;https://rubygems.org/gems/kamelopard&#34;&gt;version 0.0.15 of Kamelopard&lt;/a&gt; to RubyGems. As described in &lt;a href=&#34;/blog/2011/08/giraffes-and-liquid-galaxy/&#34;&gt;several&lt;/a&gt; &lt;a href=&#34;/blog/2011/11/kamelopard-release/&#34;&gt;previous&lt;/a&gt; &lt;a href=&#34;/blog/2013/02/kamelopard-updates/&#34;&gt;blog&lt;/a&gt; &lt;a href=&#34;/blog/2013/12/new-kamelopard-version/&#34;&gt;posts&lt;/a&gt;, Kamelopard is a Ruby gem designed to create KML documents quickly and easily. We use it to create content for our &lt;a href=&#34;https://www.visionport.com/&#34;&gt;Liquid Galaxy&lt;/a&gt; customers. This release doesn’t include any major new features, rather it provides a number of small but very helpful modifications that taken together make life much easier.&lt;/p&gt;
&lt;h3 id=&#34;new-spline-types&#34;&gt;New Spline Types&lt;/h3&gt;
&lt;p&gt;Perhaps the most useful of these new features relate to spline functions, introduced in Kamelopard version 0.0.12. The original spline function interface &lt;a href=&#34;https://code.google.com/p/liquid-galaxy/wiki/KamelopardFunctions#Multidimensional_functions&#34;&gt;described here&lt;/a&gt; accepts a series of equi-dimensional vectors as control points, and returns vectors as results, but there’s no indication of what each dimension in the vector means. This is convenient in that you can use splines to make nice paths through any number of dimensions and use them however you’d like, but in practice we most commonly want to make tours which fly through sets of either KML &lt;em&gt;Points&lt;/em&gt; or &lt;em&gt;AbstractViews&lt;/em&gt; (&lt;em&gt;Points&lt;/em&gt; include just a latitude, longitude, and altitude, but &lt;em&gt;AbstractViews&lt;/em&gt; include a direction vector, so they describe cameras and their positions). Two new classes, called &lt;em&gt;PointSplineFunction&lt;/em&gt; and &lt;em&gt;ViewSplineFunction&lt;/em&gt;, accept &lt;em&gt;Points&lt;/em&gt; and &lt;em&gt;AbstractViews&lt;/em&gt; respectively as their control points, and return those types when evaluated, freeing the user from having to map each control point’s coordinates to a simple vector.&lt;/p&gt;
&lt;p&gt;Often when creating tours, we’ll use Google Earth to find a set of views we like, save them to a KML file, and then write a script to make a tour out of those placemarks. With these new classes, that becomes much easier. Here’s an example which ingests a KML file containing several placemarks, and creates a simple spline-based tour through them, in the order in which they appear in the KML file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sp = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Kamelopard&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Functions&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ViewSpline&lt;/span&gt;.new
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;each_placemark(&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;XML&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Document&lt;/span&gt;.file(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;waypoints.kml&amp;#39;&lt;/span&gt;)) &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; |&lt;span style=&#34;color:#038&#34;&gt;p&lt;/span&gt;, v|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sp.add_control_point(w, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;..&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;30&lt;/span&gt;).each &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; |i|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fly_to sp.run_function(i.to_f/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;30&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;), &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:duration&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;8&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:mode&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:smooth&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This uses the &lt;em&gt;each_placemark&lt;/em&gt; function Kamelopard has had for quite a while to iterate through the file’s placemarks and create control points, and then calculates the value of the spline along 30 points to create the flight path. This is such a common idiom when making tours that this Kamelopard version makes it even easier with a new &lt;em&gt;fly_placemarks&lt;/em&gt; helper function. Using the new function, the code above becomes simply this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fly_placemarks &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;XML&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Document&lt;/span&gt;.file(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;waypoints.kml&amp;#39;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;more-flexible-geocoding&#34;&gt;More Flexible Geocoding&lt;/h3&gt;
&lt;p&gt;Kamelopard tries to make it easy to use geocoding services, which allow users to convert things like street addresses into latitudes and longitudes. This has its difficulties, as service providers regularly change formats or requirements, or quit the business altogether. Kamelopard has supported various geocoders in its time; this version finally adds support for Google’s service. I’d left it out in previous versions because of an incorrect understanding of Google’s licensing terms. It became important now because for the data we had from one particular client, Google’s geocoding was significantly more accurate than the MapQuest geocoder I had been using previously. For different data sets, of course, some other service might get the most accurate results, but geocoding accuracy is a big concern for the work we do. No client wants to ask their shiny new Liquid Galaxy to zoom in on the corporate headquarters and see instead a seven screen panorama of the neighboring grocery store.&lt;/p&gt;
&lt;p&gt;For geocoding projects of your own, there are a few considerations to keep in mind. First, geocoding services often impose usage limits. We’ll sometimes find when geocoding a list of addresses that the service rejects every third or fourth query simply because we’re querying faster than it wants to allow. They generally limit the number of queries allowed in one day, too, so debug your scripts using a small list of addresses before trying out a whole bunch at once. Having a project delayed simply because the geocoding service has stopped talking to you for the day is frustrating. Finally, it’s often a good idea to geocode in one step, save the results somewhere, and make the tour in a second step using the saved results. This frees you from dependence on access to the service, and allows manual tweaking of the geocoded results. Note, however, that some services’ licenses forbid saving the results anywhere.&lt;/p&gt;
&lt;p&gt;Whichever service you end up using, Kamelopard code for geocoding generally looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;g = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;GoogleGeocoder&lt;/span&gt;.new(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;my-api-key&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;results = {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Addresses&lt;/span&gt;.each &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; |t|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  results[t] = g.lookup(t)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Most services require an API key used for authorization, and return a large JSON structure which includes latitude and longitude, a status code, result quality, and any other useful information the service provider thinks you should have.&lt;/p&gt;
&lt;h3 id=&#34;other-updates&#34;&gt;Other Updates&lt;/h3&gt;
&lt;p&gt;It seems it has always been hard for newcomers to get used to Kamelopard. This version includes a number of updates to &lt;a href=&#34;http://www.rubydoc.info/gems/kamelopard/0.0.15/&#34;&gt;the documentation&lt;/a&gt;, which will hopefully make it easier for them. It also includes new helper functions for writing out all KML documents in memory at once, and creating KMZ files automatically where desired.&lt;/p&gt;
&lt;p&gt;Please give the new version a try. We’d love to hear how it’s being used.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Liquid Galaxy at the Economist World Ocean Summit</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/03/liquid-galaxy-at-economist-world-ocean/"/>
      <id>https://www.endpointdev.com/blog/2014/03/liquid-galaxy-at-economist-world-ocean/</id>
      <published>2014-03-03T00:00:00+00:00</published>
      <author>
        <name>Dave Jenkins</name>
      </author>
      <content type="html">
        &lt;table cellpadding=&#34;0&#34; cellspacing=&#34;0&#34; class=&#34;tr-caption-container&#34; style=&#34;float: right; margin-left: 1em; text-align: right;&#34;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&#34;text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2014/03/liquid-galaxy-at-economist-world-ocean/image-0-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/03/liquid-galaxy-at-economist-world-ocean/image-0.jpeg&#34;/&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&#34;tr-caption&#34; style=&#34;text-align: center;&#34;&gt;&lt;i&gt;The Liquid Galaxy with image capture equipment&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;End Point had the distinct privilege of providing a Liquid Galaxy to the &lt;em&gt;Economist World Ocean Summit&lt;/em&gt; held in Half Moon Bay, California last week. Originally conceived as a Google Earth and Google Street View platform, the Liquid Galaxy is rapidly becoming a premiere display for ocean content as well. Google is partnering with NGOs and corporations that are actively working toward ocean sustainability. Together, these organizations capture and categorize a great deal of ocean content, with most of that content publicly available via Street View. Some of this equipment was on display next to the Liquid Galaxy: a Trekker camera for remote areas and an underwater camera provided by the &lt;a href=&#34;http://catlinseaviewsurvey.com/&#34;&gt;Catlin Seaview Survey&lt;/a&gt; for capturing hi-definition panoramas underwater.&lt;/p&gt;
&lt;p&gt;This deployment used a custom configuration with six large HDTVs arrayed in a curved 3x2 panorama. The Liquid Galaxy is able to show this content as a single large surface with geometrically-adjusted angles. In short, it’s like a bay window on a submarine. Viewers are able to navigate to different locations through a touchscreen interface, and then rotate and zoom in on detailed panoramic photos with a 6-axis controller.&lt;/p&gt;
&lt;p&gt;End Point enjoys a close working relationship with Google, and is happy to provide a Liquid Galaxy for such events. Our engineer &lt;a href=&#34;/team/neil-elliott/&#34;&gt;Neil&lt;/a&gt; assembled a custom frame to hold the 3x2 screen configuration (deployed for the first time here), tested all devices, adjusted viewing angles, and then deployed and supported the full rig onsite at the Ritz-Carlton Hotel in Half Moon Bay.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;
&lt;a href=&#34;/blog/2014/03/liquid-galaxy-at-economist-world-ocean/image-1-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/03/liquid-galaxy-at-economist-world-ocean/image-1.jpeg&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;
&lt;a href=&#34;/blog/2014/03/liquid-galaxy-at-economist-world-ocean/image-2-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/03/liquid-galaxy-at-economist-world-ocean/image-2.jpeg&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;
&lt;a href=&#34;/blog/2014/03/liquid-galaxy-at-economist-world-ocean/image-3-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/03/liquid-galaxy-at-economist-world-ocean/image-3.jpeg&#34;/&gt;&lt;/a&gt;&lt;/div&gt;

      </content>
    </entry>
  
    <entry>
      <title>Newest European Liquid Galaxy installation: Google Hamburg shop-in-shop</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/10/newest-european-liquid-galaxy/"/>
      <id>https://www.endpointdev.com/blog/2013/10/newest-european-liquid-galaxy/</id>
      <published>2013-10-02T00:00:00+00:00</published>
      <author>
        <name>Bianca Rodrigues</name>
      </author>
      <content type="html">
        &lt;p&gt;In September 2013, Google opened a store-in-store within the large electronics retailer Saturn in Hamburg. Dominating the visuals of the store is a large Liquid Galaxy on the back wall.&lt;/p&gt;
&lt;img height=&#34;212&#34; src=&#34;http://www.mopo.de/image/view/2013/8/13/24308250,21727764,highRes,maxh,480,maxw,480,GoogleSaturnmenschen.jpg&#34; width=&#34;320&#34;/&gt;
&lt;p&gt;We partnered with system integrator &lt;a href=&#34;https://web.archive.org/web/20140529143009/http://www.pixelprojects.co.uk:80/&#34;&gt;Pixel Projects&lt;/a&gt; this time, and instead of our usual 7 screen display, worked the Liquid Galaxy into an unique 3x3 video wall array. The Liquid Galaxy shows Google Earth and will be showing Google Street View starting later this month, further highlighting the rich set of services offered by Google. It is also integrated with traditional video wall software configured by Pixel Projects such that it it can be switched to displaying Google services such as YouTube, Google Drive, Hangouts, and more. As always, the Liquid Galaxy is a huge customer draw. Customers who come through the store can explore any point on the globe while they browse the Google products.&lt;/p&gt;
&lt;p&gt; &lt;img height=&#34;211&#34; src=&#34;/blog/2013/10/newest-european-liquid-galaxy/image-0.jpeg&#34; style=&#34;text-align: right;&#34; width=&#34;320&#34;/&gt;&lt;/p&gt;
&lt;p&gt;End Point worked under the direction of the retail experience agency, &lt;a href=&#34;http://www.makeretail.com/&#34;&gt;Make Retail&lt;/a&gt;, to design a fully integrated experience. Once the unique configuration of the Liquid Galaxy was set, we sent along one of our top engineers, &lt;a href=&#34;/team/matt-vollrath/&#34;&gt;Matt Vollrath&lt;/a&gt;, to oversee the final hardware and software integration and installations, together with our local deployment partners Pixel.&lt;/p&gt;
&lt;p&gt;As a new step for Google in Europe, the Liquid Galaxy creates a fantastic experience for consumers and enhances the impact of the retail store.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Kamelopard update—​Panoramic camera simulation, and splines have returned</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/07/kamelopard-update-panoramic-camera/"/>
      <id>https://www.endpointdev.com/blog/2013/07/kamelopard-update-panoramic-camera/</id>
      <published>2013-07-16T00:00:00+00:00</published>
      <author>
        <name>Josh Tolley</name>
      </author>
      <content type="html">
        &lt;p&gt;A few days ago I pushed Kamelopard version 0.0.12 to &lt;a href=&#34;https://rubygems.org/gems/kamelopard&#34;&gt;RubyGems&lt;/a&gt;. This version includes a couple big items. The first of these is a new implementation of the spline code that was removed a while ago. As I mentioned in &lt;a href=&#34;/blog/2013/04/creating-smooth-flight-paths-in-google/&#34;&gt;a previous blog post&lt;/a&gt;, this original implementation was built in anticipation of an API that never materialized. The new version is built on the same API discussed in the previous post I mentioned, modified to support multidimensional functions. More information about these splines is available on the &lt;a href=&#34;https://github.com/liquidgalaxy/liquid-galaxy/wiki&#34;&gt;wiki for Liquid Galaxy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The other big new feature is the ability to simulate multiple-camera panoramic images, which we’re calling “multicam”. It has &lt;a href=&#34;https://github.com/LiquidGalaxy/liquid-galaxy/wiki/KamelopardMulticam&#34;&gt;its own wiki page&lt;/a&gt; as well, but I wanted to describe it in greater detail, because there’s a fair bit of 3D geometry involved that seemed blog-worthy. First, though, it’s important to understand the goal. In a Liquid Galaxy, each instance of Google Earth displays the view from one virtual “camera”. One display’s camera points exactly where you tell it to point; the others point to one side or the other, based on &lt;a href=&#34;https://github.com/LiquidGalaxy/liquid-galaxy/wiki/QuickStart&#34;&gt;a few settings&lt;/a&gt; in a Google Earth configuration file. When placed side-by-side in the right order, these displays form a single panoramic image. Google Earth itself figures out where these displays’ cameras should point, but for some applications, we wanted to be able to calculate those display angles and position the cameras on our own. For instance, it would sometimes be nice to pre-record a particular tour and play it back on a Liquid Galaxy as a simple video. For a seven-screen galaxy, we’ll need seven different video files, each with the same movements to and from the same geographic locations, but each with a slightly different camera orientation.&lt;/p&gt;
&lt;p&gt;Camera orientation is controlled by &lt;a href=&#34;https://developers.google.com/kml/documentation/kmlreference#abstractview&#34;&gt;KML AbstractView elements&lt;/a&gt;, of which there are two varieties: &lt;a href=&#34;https://developers.google.com/kml/documentation/kmlreference#camera&#34;&gt;Camera&lt;/a&gt;, and &lt;a href=&#34;https://developers.google.com/kml/documentation/kmlreference#lookat&#34;&gt;LookAt&lt;/a&gt;. The former tells the camera its position and orientation exactly; the latter describes it in terms of another point. For now, multicam only supports Camera objects, because LookAt is somewhat more complicated.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2013/07/kamelopard-update-panoramic-camera/image-0-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2013/07/kamelopard-update-panoramic-camera/image-0.png&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;A Camera object gives the camera’s latitude, longitude, and altitude, and three angles called heading, tilt, and roll. The camera initially points straight down, positioned so that north is up. When orienting the camera, Google Earth first rotates around the Z axis, which extends through the lens of the camera, by the heading amount. Then it rotates around the X axis, which extends through the sides of the camera, by the amount given by the tilt angle. Finally, it rotates around the Z axis again, by the roll amount. The Y axis always points in whatever direction the camera thinks is “up”.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2013/07/kamelopard-update-panoramic-camera/image-1-big.png&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2013/07/kamelopard-update-panoramic-camera/image-1.png&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;With that background, we’re ready to tackle the problem at hand. We’ll consider our cameras as shown in the drawing. Camera 0 is the master view, positively numbered cameras go off to the master camera’s right, and negatively numbered cameras to the left. Each camera has the same view angle. We want an API that will accept the master camera’s orientation, the number of the camera we’re interested in, and the view angle of each camera, and return the orientation for the camera number we gave. We’ll consider each camera’s orientation in terms of two vectors; the first will tell us what direction the camera is pointing, and the second, the up direction. I’ll call these the “camera” vector and the “up” vector. The first step will be to find these two vectors for the camera we want, and the second will be to translate that back into a Camera object.&lt;/p&gt;
&lt;p&gt;Getting the position of these vectors for any given camera is a simple application of &lt;a href=&#34;https://en.wikipedia.org/wiki/Rotation_matrix&#34;&gt;rotation matrices&lt;/a&gt;. In the Kamelopard code, there’s a function defined for rotating around each of the three axes. Here’s the example for the X axis; the others are all similar:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;rot_x&lt;/span&gt;(a)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#888&#34;&gt;# Convert the angle to radians&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   a = a * &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Math&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;PI&lt;/span&gt; / &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;180&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Matrix&lt;/span&gt;[[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;], [&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Math&lt;/span&gt;.cos(a), -&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt; * &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Math&lt;/span&gt;.sin(a)], [&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Math&lt;/span&gt;.sin(a), &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Math&lt;/span&gt;.cos(a)]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So we start with a camera pointed at the ground, and we multiply it by a rotation matrix, so that it points in the direction our camera would, before the heading, tilt, and roll rotations are applied. When we perform those rotations, we’ll end up with a vector pointed in the right direction for our camera. This code does just that.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# The camera vector is [0,0,1] rotated around the Y axis the amount&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# of the camera angle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;camera = rot_y(cam_angle) * &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Vector&lt;/span&gt;[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# The up vector is the same for all cameras&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;up = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Vector&lt;/span&gt;[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;matrix = rot_z(heading) * rot_x(tilt) * rot_z(roll)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(h, t, r) = vector_to_camera(matrix * camera, matrix * up)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The last line of this snippet calculates the camera and up vectors, and passes them to the vector_to_camera() function, which takes care of the second step in the process: converting these vectors back into a usable heading, tilt, and roll. Two operations fundamental to linear algebra will become important here. Both take two vectors as input. The &lt;a href=&#34;https://en.wikipedia.org/wiki/Dot_product&#34;&gt;dot product&lt;/a&gt; returns product of the two vectors’ magnitudes and the cosine of the angle between them. We’ll use it here to find the angle between two vectors. The &lt;a href=&#34;https://en.wikipedia.org/wiki/Cross_product&#34;&gt;cross product&lt;/a&gt; returns a &lt;a href=&#34;https://en.wikipedia.org/wiki/Surface_normal&#34;&gt;normal&lt;/a&gt; vector, or a vector which is perpendicular to the two input vectors.&lt;/p&gt;
&lt;p&gt;First we want to calculate the heading, which we can find by calculating the angle between two planes. The first plane is defined by the camera vector and the Z axis, and the second is the plane of the Y and Z axes. To find the angle between two planes, we find the angle between their normal vectors. The normal vector of the YZ plane is simply the X axis; the normal vector for hte first plane is the cross product of the camera vector and the Z axis. The dot product lets us find the angle between these two vectors, which is our heading.&lt;/p&gt;
&lt;p&gt;Tilt is simply the angle between the camera vector and the original Z axis, but roll is a bit harder. To find it, we transform the original Y axis—​the original “up” vector—​using the heading and tilt calculated previously. We then find the angle between it and the current “up” vector, again using the dot product.&lt;/p&gt;
&lt;p&gt;These calculations underlie a simple API, which simply takes a view, for the original camera, the number of the camera we’re interested in getting, and the camera angle or total number of cameras. Like this, for instance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;view_hash = {&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:latitude&lt;/span&gt; =&amp;gt; otp[&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:latitude&lt;/span&gt;], &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:longitude&lt;/span&gt; =&amp;gt; lo,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:altitudeMode&lt;/span&gt; =&amp;gt; otp[&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:altitudeMode&lt;/span&gt;], &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:altitude&lt;/span&gt; =&amp;gt; otp[&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:altitude&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:roll&lt;/span&gt; =&amp;gt; otp[&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:roll&lt;/span&gt;], &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:timestamp&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Kamelopard&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;TimeStamp&lt;/span&gt;.new(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;1921-07-29&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:heading&lt;/span&gt; =&amp;gt; otp[&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:heading&lt;/span&gt;], &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:tilt&lt;/span&gt; =&amp;gt; otp[&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:tilt&lt;/span&gt;]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Kamelopard&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Multicam&lt;/span&gt;.get_camera_view(make_view_from(view_hash), camera, &lt;span style=&#34;color:#080&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;CamCount&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


      </content>
    </entry>
  
    <entry>
      <title>Estimating overlayfs File Space Usage on Ubuntu 12.04 LiveCD</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/04/estimating-overlayfs-file-space-usage/"/>
      <id>https://www.endpointdev.com/blog/2013/04/estimating-overlayfs-file-space-usage/</id>
      <published>2013-04-24T00:00:00+00:00</published>
      <author>
        <name>Adam Vollrath</name>
      </author>
      <content type="html">
        &lt;p&gt;End Point’s &lt;a href=&#34;https://www.visionport.com/&#34;&gt;Liquid Galaxy&lt;/a&gt; platform is a cluster of computers distributing the rendering load of Google Earth and other visualization applications. Each of these “display nodes” boots the same disk image distributed over the local network. Our disk image is based on the Ubuntu 12.04 LiveCD, and uses the same &lt;a href=&#34;https://git.kernel.org/cgit/linux/kernel/git/mszeredi/vfs.git/tree/Documentation/filesystems/overlayfs.txt?h=overlayfs.current&#34;&gt;overlayfs&lt;/a&gt; to combine a read-only ISO with a writeable ramdisk. This &lt;a href=&#34;http://en.wikipedia.org/wiki/Union_mount&#34;&gt;Union mount&lt;/a&gt; uses &lt;a href=&#34;http://en.wikipedia.org/wiki/Copy-on-write&#34;&gt;Copy-on-write&lt;/a&gt; to copy files from the read-only “lower” filesystem to the virtual “upper” filesystem whenever those files or directories are opened for writing.&lt;/p&gt;
&lt;p&gt;We often allocate 4GB of system memory to the ramdisk containing the “upper” filesystem. This allows 4GB of changed files on the / filesystem, most of which are often Google Earth cache files. But sometimes the ramdisk fills up with other changes and it’s difficult to track down which files have changed unexpectedly.&lt;/p&gt;
&lt;p&gt;The df command properly displays total usage for the overlayfs “upper” filesystem mounted at /.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ df -h
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Filesystem              Size  Used Avail Use% Mounted on
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/cow                    3.9G  2.2G  1.8G  55% /
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/loop0              833M  833M     0 100% /cdrom
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/loop1              808M  808M     0 100% /rofs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But how can we identify which files are consuming that space? Because the root device has been pivoted by the casper scripts at boot, the /cow device is not readily available. We often use the du tool to estimate disk usage, but in this case it cannot tell the difference between files in the “upper” ramdisk and the “lower” read-only filesystem. To find the files filling our /cow device, we need a way to enumerate only the files in the “upper” filesystem, and then estimate only their disk usage.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;mount&lt;/code&gt; command shows the / filesystem is type “overlayfs”.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ mount
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/cow on / type overlayfs (rw)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/loop0 on /cdrom type iso9660 (ro,noatime)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/loop1 on /rofs type squashfs (ro,noatime)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The find command does indicate that most directories exist in the filesystem of type “overlayfs”, and most unmodified files are on the “lower” filesystem, in this case “squashfs”.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sudo find / -printf &amp;#39;%F\t%D\t%p\n&amp;#39; | head -n 7 ### fstype, st_dev, filename
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;overlayfs 17 /
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;overlayfs 17 /bin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;squashfs 1793 /bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;squashfs 1793 /bin/bunzip2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;squashfs 1793 /bin/bzcat
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;squashfs 1793 /bin/bzcmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;squashfs 1793 /bin/bzdiff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, the modified files are reported to be on an “unknown” filesystem on a device 16. These are the files that have been copied to the “upper” filesystem upon writing.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ find /home/lg/ -printf &amp;#39;%F\t%D\t%p\n&amp;#39; | head -n 33
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;overlayfs 17 /home/lg/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;squashfs 1793 /home/lg/.Xresources
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;unknown  16 /home/lg/.bash_history
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;squashfs 1793 /home/lg/.bash_logout
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;squashfs 1793 /home/lg/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;overlayfs 17 /home/lg/.config
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;overlayfs 17 /home/lg/.config/Google
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;unknown  16 /home/lg/.config/Google/GoogleEarthPlus.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;unknown  16 /home/lg/.config/Google/GECommonSettings.conf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I couldn’t quickly discern how find is identifying the filesystem type, but it can use the -fstype test to reliably identify files that have been modified and copied. (Unfortunately find does not have a test for device number so if you have more than one overlayfs filesystem this solution may not work for you.)&lt;/p&gt;
&lt;p&gt;Now that we have a reliable list of which files have been written to and copied, we can see which are consuming the most disk space by piping that list to du. We’ll pass it a null-terminated list of files to accommodate any special characters, then we’ll sort the output to identify the largest disk space hogs.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sudo find / -fstype unknown -print0 | du --files0-from=- --total | sort -nr | head -n 4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2214228 total
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;38600 /var/cache/apt/pkgcache.bin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;38576 /var/cache/apt/srcpkgcache.bin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;17060 /var/log/daemon.log&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We included a total in this output, and notice that total is exactly the 2.2GB indicated by the df output above, so I believe this is measuring what we intend.&lt;/p&gt;
&lt;p&gt;Of course five hundred 2MB Google Earth cache files consume more space than a single 38MB apt cache file, so we’d like to list the directories whose files are consuming the most ramdisk space. Unfortunately giving find and du depth arguments won’t work: the “unknown” filesystem doesn’t have any directories that we can see. We’ll have to parse the output, and that’s left as an exercise for the reader for now.&lt;/p&gt;
&lt;p&gt;I just realized I could’ve simply looked for files modified after boot-time and gotten very similar results, but that’s not nearly as fun. There may be a way to mount only the “upper” filesystem, but I was disappointed by the lack of documentation around overlayfs, which will &lt;a href=&#34;http://lkml.indiana.edu/hypermail/linux/kernel/1303.1/02476.html&#34;&gt;likely be included&lt;/a&gt; in the mainline 3.10 Linux kernel.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Leap Motion Controller &#43; Liquid Galaxy</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/04/leap-motion-controller-liquid-galaxy/"/>
      <id>https://www.endpointdev.com/blog/2013/04/leap-motion-controller-liquid-galaxy/</id>
      <published>2013-04-23T00:00:00+00:00</published>
      <author>
        <name>Dave Jenkins</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;object align=&#34;right&#34; height=&#34;315&#34; width=&#34;420&#34;&gt;&lt;iframe width=&#34;420&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/gy9K1LEnd0Q&#34; frameborder=&#34;0&#34; allow=&#34;autoplay; encrypted-media&#34; allowfullscreen&gt;&lt;/iframe&gt;&lt;/object&gt;&lt;/p&gt;
&lt;p&gt;We’re constantly trying out new things with our Liquid Galaxy at End Point: new content types, new remote management scripts, new hardware. The good people at &lt;a href=&#34;https://www.leapmotion.com/&#34;&gt;Leap Motion&lt;/a&gt; sent over one of their hand motion controllers and we couldn’t wait to get it unpacked and driving the Liquid Galaxy that sits in our office.&lt;/p&gt;
&lt;p&gt;With access to developer tools, we were able to configure the Leap Motion and update the device firmware. Then, after a quick installation of the latest Google Earth build v 7.1.1.1550 that includes Leap Motion controller support, we were ready to test out the new device on our 7-screen Liquid Galaxy.&lt;/p&gt;
&lt;p&gt;Watch the video and see for yourself—​we think the combination is fantastic! That superhero feeling of flying around the world with a Liquid Galaxy is only enhanced that much more by now commanding the movement of the planet with subtle flexing of your fingers. (That’s Kiel in the video—​personally, I think he looks like Magneto without the helmet.)&lt;/p&gt;
&lt;p&gt;End Point continues to push the boundaries on what the Liquid Galaxy can do. We want to experiment some more and see what else might be possible with the Leap Motion controller for Google Street View, panoramic photos, videos, and maybe even games. If you’ve got an idea, or if you have a cool place where this might be deployed, please contact us!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Creating Smooth Flight Paths in Google Earth with Kamelopard and Math</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/04/creating-smooth-flight-paths-in-google/"/>
      <id>https://www.endpointdev.com/blog/2013/04/creating-smooth-flight-paths-in-google/</id>
      <published>2013-04-15T00:00:00+00:00</published>
      <author>
        <name>Josh Tolley</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;a href=&#34;http://commons.wikimedia.org/wiki/File:Camel_in_Petra3.jpg&#34; imageanchor=&#34;1&#34; style=&#34;padding: 10px&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2013/04/creating-smooth-flight-paths-in-google/image-0.jpeg&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The major motivation for writing Kamelopard was that writing XML by hand is a pain in the neck. But there were other motivations as well. In particular we found some limitations of Google Earth’s default FlyTo behavior, and wanted to be able to address them flexibly. Version 0.0.11, just released, does exactly that.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;/blog/2013/04/creating-smooth-flight-paths-in-google/image-1-big.png&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2013/04/creating-smooth-flight-paths-in-google/image-1.png&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Bezier curve, similar to a cspline&lt;/p&gt;
&lt;p&gt;Our clients often want Google Earth’s camera to fly smoothly from one place to another, through a precisely defined set of waypoints. Earth does this with a &lt;a href=&#34;https://developers.google.com/kml/documentation/kmlreference#gxflyto&#34;&gt;FlyTo&lt;/a&gt;, one of Google’s extensions to KML. It tells Earth to move from its current camera position to a new one, following a nice path Google Earth calculates automatically. Most of the time this works just fine, but on occasion, Earth’s automatic path will run into buildings or mountains, or do other unexpected and strange things. There are a few KML tricks we’ve learned to handle those cases, but it would often be nice to have tighter control. Unfortunately getting that level of control means calculating the flight path ourselves. We’ve developed the smarts to do that, a little bit at a time.&lt;/p&gt;
&lt;p&gt;The first version involved &lt;a href=&#34;http://en.wikipedia.org/wiki/Cubic_Hermite_spline&#34;&gt;Catmull-Rom splines&lt;/a&gt;, a variant of a cubic spline (or “cspline”) that gives nice results and is fairly simple to calculate. The idea of a spline is to build a curve that passes smoothly through a set of “control points”. To achieve this, in essence we project those points into a vector space defined by a special set of cubic basis functions. In other words, we turn our control points into a matrix and multiply it by another matrix to end up with a function describing our path. The general cspline requires “tangents” in addition to the control points to define behavior at the ends of the curve; the Catmull-Rom variant derives the tangents from the control points, which limits flexibility but works well for our purposes. So if we want a path between several points on a globe, we use those points as the control points in the spline, and Kamelopard would make a nice path between them automatically. Better still, csplines can support any number of dimensions, so we can include factors such as altitude or heading in the generated curve. As it turned out, though, we didn’t end up using this spline very much. It was built on top of some other code that later proved insufficient for what we wanted, and that was removed.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;/blog/2013/04/creating-smooth-flight-paths-in-google/image-2-big.png&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2013/04/creating-smooth-flight-paths-in-google/image-2.png&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Parabola defined by three points&lt;/p&gt;
&lt;p&gt;The next iteration, recently committed, allows Kamelopard scripts to define mathematical functions in terms of the same control points, and asks Kamelopard to use those functions to build smooth paths. Right now Kamelopard supports cubic, quadratic, and linear functions; others would of course be possible given sufficient reason to develop them, but the existing functions seem to work very well. The matrix math to interpolate these types of functions based on control points was straightforward, and they can define a wide variety of paths.&lt;/p&gt;
&lt;p&gt;One limitation of the new code compared to the old: the spline functions would take any number of control points, whereas the mathematical function versions are more limited. Three points in a particular order, for instance, uniquely describe a quadratic curve. As a result, our quadratic function implementation only supports three control points. I plan to reintroduce splines in the future for situations where this limitation causes problems. These functions are especially flexible, though, in that they can determine not only the camera’s latitude and longitude, but also its heading, altitude, and various other things including the duration of each FlyTo. Our cspline implementation was intended to handle those dimensions as well, but never got that far along.&lt;/p&gt;
&lt;p&gt;So how does all this work? Here is a simple example, showing an interpolated path from a point about 10 km above one of the cows near my house, to another point a bit to the north. First, the &lt;a href=&#34;https://josh.endpointdev.com/kamelopard_functions.kml&#34;&gt;KML itself is available for download&lt;/a&gt;; in Google Earth, it looks like this (click on the image to get the larger version):&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;/blog/2013/04/creating-smooth-flight-paths-in-google/image-3-big.png&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2013/04/creating-smooth-flight-paths-in-google/image-3.png&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here’s the code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;kamelopard&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080&#34;&gt;include&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Kamelopard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080&#34;&gt;include&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Kamelopard&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Functions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a = make_function_path(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;10&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:latitude&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Line&lt;/span&gt;.interpolate(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;38&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;8&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;40&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:longitude&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Cubic&lt;/span&gt;.interpolate(-&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;112&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;4&lt;/span&gt;, -&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;111&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;9&lt;/span&gt;, -&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;5&lt;/span&gt;, -&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;113&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;5&lt;/span&gt;, -&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;110&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:altitude&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Line&lt;/span&gt;.interpolate(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;10000&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2000&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:heading&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Line&lt;/span&gt;.interpolate(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;90&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:tilt&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Line&lt;/span&gt;.interpolate(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;40&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;90&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:altitudeMode&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:absolute&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:show_placemarks&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:duration&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Quadratic&lt;/span&gt;.interpolate(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;4&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;name_document &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;Functions test&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;name_folder &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;Placemarks&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;name_tour &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;Function test&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;write_kml_to &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;doc.kml&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The make_function_path call does most of the work here. We’ve given it functions to interpolate the latitude, longitude, and other characteristics of the flight path we want, along with a few other options described in the gem documentation. We also tell it how many points to create in the path, in this case 10. The root of the flying is still Google Earth’s FlyTo algorithm, but we set to &lt;em&gt;smooth&lt;/em&gt; mode, to keep Earth doing more precisely what we want it to, and we create waypoints on the flight path frequently enough that we have tight control over where Earth actually flies.&lt;/p&gt;
&lt;p&gt;Creating the functions themselves is relatively easy, but you need to remember the order of the arguments, which in this case at least can be confusing. I’ll probably change it in a future version, once I come up with something better. This code defines the latitude function in terms of the beginning and ending latitude, and that’s all since we only need two points to define a line. The quadratic and cubic functions take three and four points, respectively. Although not demonstrated here, make_function_paths can also take a code block for more complex behaviors at each point.&lt;/p&gt;
&lt;p&gt;In the end this generates a Google Earth Tour, which flies from the start point to the end point very smoothly. This code has demonstrated that it works well for flights over large areas; my next goal is to use it to navigate between 3D buildings on a precisely defined path. That will be for another article, though.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Kamelopard Updates</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/02/kamelopard-updates/"/>
      <id>https://www.endpointdev.com/blog/2013/02/kamelopard-updates/</id>
      <published>2013-02-15T00:00:00+00:00</published>
      <author>
        <name>Josh Tolley</name>
      </author>
      <content type="html">
        &lt;p&gt;I’ve just pushed &lt;a href=&#34;https://rubygems.org/gems/kamelopard&#34;&gt;Kamelopard v0.0.10&lt;/a&gt; to RubyGems. With the last couple of releases, Kamelopard has gained a couple of useful features I felt deserved some additional attention.&lt;/p&gt;
&lt;h3 id=&#34;support-for-viewsyncrelay-actions&#34;&gt;Support for viewsyncrelay actions&lt;/h3&gt;
&lt;p&gt;Many of our Liquid Galaxy tours require more than just Google Earth. For instance, it’s not uncommon to want audio or video media to play at a certain point in the tour. We may want our Liquid Galaxy enabled panoramic image viewer to start up and display an image, or perhaps we need to signal some other external process. Unfortunately Google Earth tours don’t support configuration to run these actions directly upon reaching a certain point, but there are alternatives. Google Earth synchronizes nodes in a Liquid Galaxy with what are called ViewSync packets, which tell all the slave nodes exactly where a master node’s camera is positioned, in terms of latitude, longitude, tilt, etc. We can watch this traffic to determine the master node’s progress through a tour and trigger actions at defined locations, and we use an application called viewsyncrelay (available &lt;a href=&#34;http://code.google.com/p/liquid-galaxy/source/browse/gnu_linux/home/lg/bin/viewsyncrelay.pl&#34;&gt;here&lt;/a&gt;) to do exactly that. We configure viewsyncrelay to run certain &lt;em&gt;actions&lt;/em&gt; when the ViewSync traffic matches a set of constraints. For instance, an action might require ViewSync packets to fall within a certain latitude, longitude, altitude, and heading, and a particular previous action might have to run first in order to activate this one.&lt;/p&gt;
&lt;p&gt;This works well enough for most purposes, but the viewsyncrelay configuration files can become complicated, and difficult to debug. Here’s where Kamelopard comes in. Now, the same code that creates a tour can create viewsyncrelay actions. Here’s an example. The code is still a bit unwieldy; it will get simpler and more elegant in future versions, after we’ve seen the best ways people come up with to use the feature.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;kamelopard&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;name_folder &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;test&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;name_document &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;test&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pt = point &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pl = placemark &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;test placemark&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:geometry&lt;/span&gt; =&amp;gt; pt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;get_folder &amp;lt;&amp;lt; pl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Kamelopard&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;VSRAction&lt;/span&gt;.new(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;action name&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:action&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;mplayer play_this_video.webm&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:constraints&lt;/span&gt; =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:latitude&lt;/span&gt; =&amp;gt; to_constraint(band(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;).collect{ |l| lat_check(l) }),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:longitude&lt;/span&gt; =&amp;gt; to_constraint(band(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;).collect{ |l| long_check(l) }),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;write_kml_to &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;doc.kml&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;write_actions_to &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;actions.yml&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In addition to the VSRAction object, these changes introduce a few new functions, including those shown here: band(a, b) returns a +/- b, in an array; lat_check() and long_check() ensure each value in the array is a valid latitude or longitude; and to_constraint() turns this validated array into a string suitable for use in a viewsyncrelay constraint. As I mentioned, this may prove awkward, but it’s a first step. This code creates a file called actions.yml, ready for use in viewsyncrelay:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;actions:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- name: action name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  input: ALL
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  action: mplayer play_this_video.webm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  repeat: DEFAULT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  constraints:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    :latitude: ! &amp;#39;[-80.1, -79.9]&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    :longitude: ! &amp;#39;[99.9, 100.1]&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;masterslave-modes&#34;&gt;Master/slave modes&lt;/h3&gt;
&lt;p&gt;Liquid Galaxy tours often consist of two different KML files: one to run on the master, and another to run on each of the slaves. The slave versions generally don’t include all of the screen overlay and network link objects used by the master, in particular, but there are plenty of objects that you might not want on the slaves. In the past we’ve had to edit the KML files manually to remove unnecessary objects, which is of course error prone, sometimes difficult, and something we have to redo every time we run our Kamelopard script and create a new tour version. Now, Kamelopard supports tagging objects as “master-only”, and creating KML documents in either normal or master-only mode, to make this process entirely automatic. Here’s an example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;kamelopard&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;name_folder &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;test&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;name_document &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;test&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pt = point &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pl = placemark &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;test placemark&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:geometry&lt;/span&gt; =&amp;gt; pt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;get_folder &amp;lt;&amp;lt; pl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;get_folder.master_only = &lt;span style=&#34;color:#080&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;write_kml_to &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;slave.kml&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;get_document.master_mode = &lt;span style=&#34;color:#080&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;write_kml_to &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;master.kml&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This results in two files, called master.kml and slave.kml. Only master.kml contains the Folder object:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&amp;lt;!--?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?--&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;kml&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;xmlns=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;http://www.opengis.net/kml/2.2&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;xmlns:atom=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;http://www.w3.org/2005/Atom&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;xmlns:gx=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;http://www.google.com/kml/ext/2.2&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;xmlns:kml=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;http://www.opengis.net/kml/2.2&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;document&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Document_1&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;test&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;visibility&amp;gt;&lt;/span&gt;1&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/visibility&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;open&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/open&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;folder&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Folder_2&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;test&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;visibility&amp;gt;&lt;/span&gt;1&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/visibility&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;open&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/open&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;placemark&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Placemark_4&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;test placemark&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;visibility&amp;gt;&lt;/span&gt;1&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/visibility&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;open&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/open&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;point&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Point_3&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;coordinates&amp;gt;&lt;/span&gt;100.0, 100.0, 0&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/coordinates&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;extrude&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/extrude&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;altitudemode&amp;gt;&lt;/span&gt;clampToGround&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/altitudemode&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/point&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/placemark&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/folder&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/document&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/kml&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The slave is essentially empty, because we didn’t tell Kamelopard about any objects that weren’t master-only:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&amp;lt;!--?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?--&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;kml&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;xmlns=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;http://www.opengis.net/kml/2.2&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;xmlns:atom=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;http://www.w3.org/2005/Atom&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;xmlns:gx=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;http://www.google.com/kml/ext/2.2&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;xmlns:kml=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;http://www.opengis.net/kml/2.2&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;document&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id=&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Document_1&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;test&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;visibility&amp;gt;&lt;/span&gt;1&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/visibility&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;open&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/open&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/document&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;lt;/kml&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;new-repository&#34;&gt;New repository&lt;/h3&gt;
&lt;p&gt;Since Kamelopard is developed primarily for our use creating Liquid Galaxy tours, it has been moved from github to a portion of the &lt;a href=&#34;https://github.com/liquidgalaxy/liquid-galaxy&#34;&gt;GitHub Liquid Galaxy project&lt;/a&gt;. Clone the repository at &lt;a href=&#34;https://github.com/liquidgalaxy/liquid-galaxy&#34;&gt;https://github.com/liquidgalaxy/liquid-galaxy&lt;/a&gt; to get your own copy, or install the gem from rubygems to play around.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Josh Tolley: About Google Earth Tours</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/06/josh-tolley-spoke-on-building-of-tours/"/>
      <id>https://www.endpointdev.com/blog/2012/06/josh-tolley-spoke-on-building-of-tours/</id>
      <published>2012-06-14T00:00:00+00:00</published>
      <author>
        <name>Josh Ausborne</name>
      </author>
      <content type="html">
        &lt;p&gt;Josh Tolley spoke on the building of tours for viewing within Google Earth and the Liquid Galaxy. It seems that everybody has data and wants a way to view it, such as businesses who want to visually represent where their customers are based, or even documenting where lightning strikes within a certain region. Google Earth is a fantastic tool for the viewing of this data.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.flickr.com/photos/80083124@N08/7186648301/&#34;&gt;&lt;img alt=&#34;IMG_0792.JPG&#34; height=&#34;375&#34; src=&#34;/blog/2012/06/josh-tolley-spoke-on-building-of-tours/image-0.jpeg&#34; width=&#34;500&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Josh talked about what is required to display geographical data in Google Earth. The data needs to go through the process of geocoding, which is the conversion to latitudinal and longitudinal format. As this is a tedious process, it is highly recommended to use a script and loop through the conversion. Google Earth is based upon KML documents, which are XML documents that contain geographical data. He explained some of the different ways to create the KML documents, including the use of Google Earth itself, writing by hand, or using a tool such as kamelopard or PyKML to create the data.&lt;/p&gt;
&lt;p&gt;He demonstrated how a KML file can contain data such as placemarks, polygons, time lapses, overlays, and animations, and he showed his own farm with an overlay placed in the wheat field. Now the zombies know where to find wheat. Josh talked about the uses of Google Earth tours, including the display of ocean currents, tsunami shock waves, wind patterns, and even historical events with a time lapse.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/LiquidGalaxy/kamelopard&#34;&gt;Kamelopard&lt;/a&gt; is a Ruby-based KML writer that Josh created. It uses Ruby code to identify a point, fly to it, stay there for a bit, then fly to the next place. It loops through all of the coordinates given and creates a tour. An example tour that Josh has written is one for Google’s Ocean Conservation Group, which displays fishery data around the world.&lt;/p&gt;
&lt;p&gt;KML can handle large datasets, and has multiple ways of being displayed. It can have regions and ground overlays, and combining the two can show increasingly detailed images and sets of placemarks as the level of zoom increases. DataAppeal can create maps with various models in them, scaling and coloring them based upon users’ data.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Giraffes and Liquid Galaxy</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2011/08/giraffes-and-liquid-galaxy/"/>
      <id>https://www.endpointdev.com/blog/2011/08/giraffes-and-liquid-galaxy/</id>
      <published>2011-08-25T00:00:00+00:00</published>
      <author>
        <name>Josh Tolley</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/File:Al_Ain_Zoo_Giraffe.JPG&#34; onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34;&gt;&lt;img alt=&#34;&#34; border=&#34;0&#34; src=&#34;/blog/2011/08/giraffes-and-liquid-galaxy/image-0.jpeg&#34; style=&#34;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 614px; height: 411px;&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We build lots and lots of Google Earth tours, typically for use with a &lt;a href=&#34;https://www.visionport.com/&#34;&gt;Liquid Galaxy&lt;/a&gt;. These tours tell Google Earth to start at one point and fly to another, displaying various images along the way. They’re written in an XML-based language called &lt;a href=&#34;https://en.wikipedia.org/wiki/Keyhole_Markup_Language&#34;&gt;Keyhole Markup Language&lt;/a&gt;, or &lt;a href=&#34;https://developers.google.com/kml/documentation/kmlreference?csw=1&#34;&gt;KML&lt;/a&gt;. Various KML elements describe points on the globe, 3D objects, tracks through space, or other items, and a series of Google-specific KML extensions can define an automated tour in which Google Earth flies through these objects.&lt;/p&gt;
&lt;p&gt;Now for a bit of dogma: writing large volumes of XML by hand is a drag. Writing KML is no exception. So when I started building KML tours, I was keen to build or find tools to make it easier. For my first KML project, making a tour through each End Point employee’s home city, I built a Perl script to convert a file of employee data to KML. This worked well enough, but I soon learned typing out all the KML was just half the pain. The other half was adjusting camera paths, camera angles, timing, and all sorts of other little things. Unfortunately all these adjustments had to be done by trial and error, and all by hand. Getting Google Earth’s camera to circle a particular point, for instance, takes about three screens worth of KML code. If a point’s coordinates were off or a tour’s timing wasn’t quite right, I had to find the right spot in a vast field of KML, tweak a number, and try it all again.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&#34;https://github.com/eggyknap/Kamelopard&#34;&gt;Kamelopard&lt;/a&gt;. Named, as dictated by long-standing &lt;a href=&#34;https://www.bucardo.org&#34;&gt;End Point tradition&lt;/a&gt;, after a strange animal, Kamelopard is a Ruby gem designed to make all this easier (“Camelopard” is the ancient English word for “giraffe” and several mythical and heraldic giraffe-like creatures; the various modern giraffe sub-species are grouped under the name &lt;em&gt;Giraffa camelopardalis&lt;/em&gt;). Right now it’s not much more than a set of classes which mirror the basic KML objects—​or most of them, anyway—​but already it has proven itself very useful. For instance, for one project we’re working on, a Ruby script of about 150 lines uses Kamelopard to digest a set of data files and produce a 12,000 line KML file. Fortunately, Kamelopard is sufficiently flexible that I can finish adjusting all the timing and camera angles and other details in the Ruby code, without having to dig through the KML output itself; we can regenerate the KML with whatever tweaks we need, as often as we need it.&lt;/p&gt;
&lt;p&gt;As a very simple example, here’s a Kamelopard script to turn a CSV file into KML. The CSV contains the name, description, latitude, and longitude of a bunch of placemarks (e.g. “Mount Everest”,“The world’s tallest mountain”,“27d58m37.15s N”,“86d55m15.93s E”), and the script turns them into KML, including a Google Earth tour that will fly past each in turn. The KML result amounts to about 45 lines per placemark, so the Ruby version is much more concise and much simpler to modify.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;kamelopard&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;csv&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;CSV&lt;/span&gt;.foreach(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;placemarks.csv&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; |a|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pl = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Placemark&lt;/span&gt;.new a[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;], point(a[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;], a[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pl.description = a[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mod_popup_for pl, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fly_to pl, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pause &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mod_popup_for pl, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;puts&lt;/span&gt; get_kml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Along with its library of classes, Kamelopard does have a (fairly unorganized, ad hoc) set of helper functions which I hope one day will evolve into a full-fledged domain-specific language. While they’re currently loosely organized and none too intelligent, there are a few jewels worth noting. For instance, my multi-page KML to orbit a point takes one line of Kamelopard. Conversion from one latitude / longitude notation to another happens automatically (manually converting 24°10’44.3994” N, 55°44’25.7274” E to the decimal notation KML requires becomes a dreary task when performed manually for ten or twenty different points). Finally, Kamelopard includes a helper function for Google’s Geocoding API, so users can translate addresses and location names to latitude and longitude.&lt;/p&gt;
&lt;p&gt;Kamelopard’s future development will most likely follow whatever lines our clients, and any contributors that care to help out, most wish to pursue, but I suspect it will include increased automation of tour timing, so developers don’t need to figure out timings for each step in a tour manually, and more helper functions to create objects, so users don’t have to instantiate classes directly, and can get more done in a line of code.&lt;/p&gt;
&lt;p&gt;I imagine the audience is fairly small, but I’d welcome any feedback, suggestions, patches, and interest.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Google Earth KML Tour Development Challenges on Liquid Galaxy</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2011/02/google-earth-kml-tour-development/"/>
      <id>https://www.endpointdev.com/blog/2011/02/google-earth-kml-tour-development/</id>
      <published>2011-02-24T00:00:00+00:00</published>
      <author>
        <name>Adam Vollrath</name>
      </author>
      <content type="html">
        &lt;p&gt;Because Liquid Galaxy runs Google Earth, it can easily visualize an organization’s GIS data. End Point also develops tours within Google Earth to better present this data. A Liquid Galaxy’s networked multi-system architecture presents unique technical challenges to these tours.&lt;/p&gt;
&lt;p&gt;Many Google Earth tours incorporate &lt;a href=&#34;https://developers.google.com/kml/documentation/touring?csw=1#updates&#34;&gt;animations and dynamic updates&lt;/a&gt; using the &lt;code&gt;&amp;lt;gx:AnimatedUpdate&amp;gt;&lt;/code&gt; element. KML features in the Earth environment can be modified, changed, or created during a tour, including the size, style, and location of placemarks, the addition of ground overlays, geometry, and more.&lt;/p&gt;
&lt;p&gt;However, these updates are only executed on the Liquid Galaxy master system running the tour, not sent to its slaves. Liquid Galaxy nodes communicate primarily via &lt;a href=&#34;https://github.com/LiquidGalaxy/liquid-galaxy/wiki/GoogleEarth_ViewSync&#34;&gt;ViewSync UDP datagrams&lt;/a&gt;. These datagrams contain only the master’s position in space and time. This means we cannot use &lt;code&gt;&amp;lt;gx:AnimatedUpdate&amp;gt;&lt;/code&gt; to animate features across all Liquid Galaxy systems, sharply limiting its utility.&lt;/p&gt;
&lt;p&gt;But tours can also &lt;a href=&#34;https://developers.google.com/kml/documentation/time?csw=1&#34;&gt;use chronological elements&lt;/a&gt; to display, animate, and hide features. Using &lt;code&gt;&amp;lt;gx:TimeSpan&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;gx:TimeStamp&amp;gt;&lt;/code&gt; within an tour stop enables flying to a specific location in space &lt;em&gt;and&lt;/em&gt; time. All Google Earth features may be assigned a TimeStamp, and all Liquid Galaxy screens display the same chronological range of features. This works around the single-system limitation on animation, and enables sweeping changes across all screens. The picture below shows a data animation in progress across three screens; the green dots are filling in the area previously occupied by the red dots, while the time sliders in the upper left corners advance.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;/blog/2011/02/google-earth-kml-tour-development/image-0.jpeg&#34; onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34;&gt;&lt;img alt=&#34;&#34; border=&#34;0&#34; id=&#34;BLOGGER_PHOTO_ID_5577750933549080418&#34; src=&#34;/blog/2011/02/google-earth-kml-tour-development/image-0.jpeg&#34; style=&#34;display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 720px;&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Taking this technique a step further, we also “wrapped” some very large KML datasets in NetworkLink elements, and wrapped those NetworkLinks in Folder elements with TimeStamp elements as well. This allowed fine control over when to fetch and render the large set, just-in-time to be featured in its own tour. These large loads can cause the Earth client to stutter, so we also stopped the flight motion and displayed a balloon full of text for the audience. A KML example of this wrapper is below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;Folder&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;name&amp;gt;Region Link Two&amp;lt;/name&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;TimeStamp&amp;gt;&amp;lt;when&amp;gt;2010-09-19T16:00:00Z&amp;lt;/when&amp;gt;&amp;lt;/TimeStamp&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;NetworkLink&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;lt;name&amp;gt;Region Link Two&amp;lt;/name&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;lt;Region&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &amp;lt;LatLonAltBox&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &amp;lt;north&amp;gt;41.8&amp;lt;/north&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &amp;lt;south&amp;gt;41.6&amp;lt;/south&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &amp;lt;east&amp;gt;-86.1&amp;lt;/east&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &amp;lt;west&amp;gt;-86.3&amp;lt;/west&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &amp;lt;/LatLonAltBox&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &amp;lt;Lod&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &amp;lt;minLodPixels&amp;gt;256&amp;lt;/minLodPixels&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &amp;lt;maxLodPixels&amp;gt;-1&amp;lt;/maxLodPixels&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &amp;lt;/Lod&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;lt;/Region&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;lt;Link&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &amp;lt;href&amp;gt;network_view.kml&amp;lt;/href&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &amp;lt;viewRefreshMode&amp;gt;onRegion&amp;lt;/viewRefreshMode&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;lt;/Link&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/NetworkLink&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/Folder&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These techniques, and the Liquid Galaxy platform, combine to coordinate a moving visual experience across the audience’s entire field of view. Animations highlight GIS data and narrate its story, creating an impressive presentation.&lt;/p&gt;

      </content>
    </entry>
  
</feed>
