text:
A scholar who never travels but stays at home is not worthy to be accounted a scholar. From my youth on I had the ambition to travel, but could not afford to wander over the three hundred counties of Korea, much less the whole world. So, carrying out an ancient practise, I drew a geographical atlas. And while gazing at it for long stretches at a time I feel as though I was carrying out my ambition . . . Morning and evening while bending over my small study table, I meditate on it and play with it and there in one vast panorama are the districts, the prefectures and the four seas, and endless stretches of thousands of miles.
Korean Student
Preface to his untitled manuscript atlas of China during the Ming Dynasty, dated 1721.
To say that maps are important is an understatement almost as big as the world itself. Maps quite literally connect us to the world in which we all live, and by extension, they link us to one another. The oldest preserved maps date back nearly 4500 years. In addition to connecting us to our past, they chart much of human progress and expose the relationships among people through time.
Unfortunately, as a work of humankind, maps share many of the same shortcomings of all human endeavors. They are to some degree inaccurate and they reflect the bias of the map maker. Advancements in technology help to address the former issue, and offer us the opportunity to resist the latter. To the extent that it's possible for all of us to participate in the map making, the bias of a select few becomes less meaningful.
Google Earth and Google Maps are two applications that allow each of us to assert our own place in the world and contribute our own unique perspective. I can think of no better way to accomplish this than by combining maps and photography.
Photos reveal much about who we are, the places we have been, the people with whom we have shared those experiences, and the significant events in our lives. Pinning our photos to a map allows us to see them in their proper geographic context, a valuable way to explore and share them with friends and family. Photos can reveal the true character of a place, and afford others the opportunity to experience these destinations, perhaps faraway and unreachable for some of us, from the perspective of someone who has actually been there.
In this tutorial I'll show you how to 'pin' your photos using Google Earth and Google Maps. Both applications are free, and available for Windows, Mac OS X, and Linux. In the case of Google Earth there are requirements associated with installing and running what is a local application. Google Maps has its own requirements: primary among them a compatible web browser (the highly regarded FireFox is recommended).
In Google Earth, your photos show up on the map within the application complete with titles, descriptions, and other relevant information. You can choose to share your photos with everyone, only people you know, or even reserve them strictly for yourself.
Google Maps offers the flexibility to present maps outside of a traditional application. For example you can embed a map on a webpage pinpointing the location of one particular photo, or mapping a collection of photos to present along with a photo gallery, or even collecting all of your digital photos together on one dynamic map.
Over the course of a short couple of articles we'll cover everything you need to take advantage of both applications. I've put together two scripts to help us accomplish that goal. The first is a Perl script that works through your photos and generates a file in the proper format with all of the data necessary to include those photos in Google Earth. The second is a short bit of Javascript that works with the first file and builds a dynamic Google Map of those same photos. Both scripts are available for you to download, after which you are free to use them as is, or modify them to suit your own projects. I've purposefully kept the code as simple as possible to make them accessible to the widest audience, even those of you reading this who may be new to programming or unfamiliar with Perl, Javascript or both. I've taken care to comment the code generously so that everything is plainly obvious. I'm hopeful that you will be surprised at just how simple it is.
There a couple of preliminary topics to examine briefly before we go any further.
In the preceding paragraph I mentioned that the result of the first of our two scripts is a 'file in the proper format...'. This file, or more to the point the file format, is a very important part of the project. KML (Keyhole Markup Language) is a fairly simple XML-based format that can be considered the native "language" of Google Earth. That description begs the question, 'What is XML?'.
To oversimplify, because even a cursory discussion of XML is outside of the scope of this article, XML (Extensible Markup Language) is an open data format (in contrast to proprietary formats) which allows us to present information in such way that we communicate not only the data itself, but also descriptive information about the data and the relationships among elements of the data. One of the technical terms that applies is 'metalanguage', which approximately translates to mean a language that makes it possible to describe other languages. If you're unfamiliar with the concept, it may be difficult to grasp at first or it may not seem impressive. However, metalanguages, and specifically XML, are an important innovation (I don't mean to suggest that it's a new concept. In fact XML has roots that are quite old, relative to the brief history of computing). These metalanguages make it possible for us to imbue data with meaning such that software can make use of that data. Let's look at an example taken from the Wikipedia entry for KML.
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<description>New York City</description>
<name>New York City</name>
Ignore all of the pro forma stuff before and after the <Placemark>
Let's think about this for a moment. There are a very large number of recognizable places on the planet, and a provably infinite number of strings. Given a block of text, how could a computer be made to identify a place from, for example the scientific name of a particular flower, or a person's name? It would be extremely difficult.
We could try to create a database of every recognizable place and have the program check the database every time it encounters a string. That assumes it's possible to agree on a 'complete list of every place', which is almost certainly untrue. Keep in mind that we could be talking about informal places that are significant only to a small number of people or even a single person, e.g. 'the park where, as a child, I first learned to fly a kite'. It would be a very long list if we were going to include these sorts of places, and incredibly time-consuming to search.
Relying on the structure of the fragment above, we can easily write a program that can identify 'New York City' as the name of a place, or for that matter 'The park where I first learned to fly a kite'. In fact, I could write a program that pulls all of the place names from a file like this, along with a description, and a pair of coordinate points for each, and includes them on a map. That's exactly what we're going to do. KML makes it possible.
If I haven't made it clear, the structural bits of the file must be standardized. KML supports a limited set of elements (e.g. 'Placemark' is a supported element, as are 'Point' and 'coordinates'), and all of the elements used in a file must adhere to the standard for it to be considered valid.
The second point we need to address before we begin is, appropriately enough... where to begin? Lewis Carroll famously tells us to "Begin at the beginning and go on till you come to the end: then stop." Of course, Mr. Carroll was writing a book at the time. If "Alice's Adventures in Wonderland" were an article, he might have had different advice. From the beginning to the end there is a lot of ground to cover. We're going to start somewhere further along, and make up the difference with the following assumptions. For the purposes of this discussion, I am going to assume that you have:
- Perl
- Access to Phil Harvey's excellent ExifTool , a Perl library and command-line application for reading, writing, and editing metadata in images (among other file types). We will be using this library in our first script
- A publicly accessible web server. Google requires the use of an API key by which it can monitor the use of its map services. Google must be able to validate your key, and so your site must be publicly available. Note that this a requirement for Google Maps only
- Photos, preferably in a photo management application. Essentially, all you need is an app capable of generating both thumbnails and reduced size copies of your original photos . An app that can export a nice gallery for use on the web is even better
- Coordinate data as part of the EXIF metadata embedded in your photos. If that sounds unfamiliar to you, then most likely you will have to take some additional steps before you can make use of this tutorial. I'm not aware of any digital cameras that automatically include this information at the time the photo is created. There are devices that can be used in combination with digital cameras, and there are a number of ways that you can 'tag' your photos with geographic data much the same way you would add keywords and other annotations.
Let's begin!
Part 1: Google Earth
Section 1: Introduction to Part 1
Time to begin the project in earnest. As I've already mentioned we'll spend the first half of this tutorial looking at Google Earth and putting together a Perl script whichthat, given a collection of geotagged photos, will build a set of KML files so that we can browse our photos in Google Earth. These same files will serve as the data source for our Google Maps application later on.
Section 2: Some Advice Before We Begin
Take your time to make sure you understand each topic before you move on to the next. Think of this as the first step in debugging your completed code. If you go slowly enough that you are to be able to identify aspects of the project that you don't quite understand, then you'll have some idea where to start looking for problems should things not go as expected. Furthermore, going slowly will give you the opportunity to identify those parts that you may want to modify to better fit the script to your own needs.
If this is new to you, follow along as faithfully as possible with what I do here the first time through. Feel free to make notes for yourself as you go, but making changes on the first pass may make it difficult for you to catch back on to the narrative and piece together a functional script. After you have a working solution, it will be a simple matter to implement changes one at a time until you have something that works for you. Following this approach it will be easy to identify the silly mistakes that tend to creep in once you start making changes.
There is also the issue of trust. This is probably the first time we're meeting each other, in which case you should have some doubt that my code works properly to begin with. If you minimize the number of changes you make, you can confirm that this works for you before blaming yourself or your changes for my mistakes. I will tell you up front that I'm building this project myself as we go. You can be certain at least that it functions as described for me as of the date attached to the article. I realize that this is quite different from being certain that the project will work for you, but at least it's something.
The entirety of my project is available for you to download. You are free to use all of it for any legal purpose whatsoever, including my photos in addition to all of the code, icons, etc. This is so you have some samples to use before you involve your own content. I don't promise that they are the most beautiful images you have ever seen, but they are all decent photos and properly annotated with the necessary metadata, including geographic tags.
Section 3: Photos, Metadata and ExifTool
To begin, we must have a clear understanding of what the Perl script will require from us. Essentially, we need to provide it with a selection of annotated image files, and information about how to reference those files.
A simple folder of files is sufficient, and will be convenient for us, both as the programmer and end user. The script will be capable of negotiating nested folders, and if a directory contains both images and other file types, non-image types will be ignored.
Typically, after a day of taking photos I'll have 100 to 200 that I want to keep. I delete the rest immediately after offloading them from the camera. For the files that are left, I preserve the original grouping, keeping all of the files together in a single folder. I place this folder of images in an appropriate location according to a scheme that serves to keep my complete collection of photos neatly organized. These are my digital 'negatives'. I handle all subsequent organization, editing, enhancements, and annotations within my photo management application. I use Apple Inc.'s Aperture; but there are many others that do the job equally well.
Annotating your photos is well worth the investment of time and effort, but it's important that you have some strategy in mind so that you don't create meaningless tags that are difficult to use to your advantage. For the purposes of this project the tags we'll need are quite limited, which means that going forward we will be able to continue adding photos to our maps with a reasonable amount of work.
The annotations we need are:
Image Date *
Country Name
ImageWidth *
ImageHeight *
* Values for these Exif tags are generated by your camera.
Note that these are labels used in Aperture, and are not necessarily consistent from one application to the next. Some of them are more likely than others to be used reliably. 'City' for example should be dependable, while the labels 'People', 'Events', and 'Location', among others, are more likely to differ. One explanation for these variations is that the meaning of these fields are more open to interpretation. Location, for example, is likely to be used to narrow down the area where the photo was taken within a particular city, but it is left to the person who is annotating the photo to decide that the field should name a specific street address, an informal place (e.g. 'home' or 'school'), or a larger area, for example a district or neighborhood. Fortunately things aren't so arbitrary as they seem.
Each of these fields corresponds to a specific tag name that adheres to one of the common metadata formats (Exif1, IPTC2, XMP3, and there are others). These tag names are consistent as required by the standards. The trick is in determining the labels used in your application that correspond to the well-defined tag names. Our script relies on these metadata tags, so it is important that you know which fields to use in your application.
This gives us an excuse to get acquainted with ExifTool4. From the project's website, we have this description of the application:
ExifTool is a platform-independent Perl library plus a command-line application for reading, writing, and editing meta information in image, audio, and video files...
ExifTool can seem a little intimidating at first. Just keep in mind that we will need to understand just a small part of it for this project, and then be happy that such a useful and flexible tool is freely available for you to use.
The brief description above states in part that ExifTool is a Perl library and command line application that we can use to extract metadata from image files.
With a single short command, we can have the app print all of the metadata contained in one of our image files. First, make sure ExifTool is installed. You can test for this by typing the name of the application at the command line.
$ exiftool
If it is installed, then running it with no options should prompt the tool to print its documentation. If this works, there will be more than one screen of text. You can page through it by pressing the spacebar. Press the 'q' key at any time to stop.
If the tool is not installed, you will need to add it before continuing. See the appendix at the end of this tutorial for more information.
Having confirmed that ExifTool is installed, typing the following command will result in a listing of the metadata for the named image:
$ exiftool -f -s -g2 /path/image.jpg
Where 'path' is an absolute path to image.jpg or a relative path from the current directory, and 'image.jpg' is the name of one of your tagged image files.
We'll have more to say about ExifTool later, but because I believe that no tutorial should ask the reader to blindly enter commands as if they were magic incantations, I'll briefly describe each of the options used in the command above:
-f, forces printing of tags even if their values are not found. This gives us a better idea about all of the available tag names, whether or not there are currently defined values for those tags.
-s, prints tag names instead of descriptions. This is important for our purposes. We need to know the tag names so that we can request them in our Perl code. Descriptions, which are expanded, more human-readable forms of the same names obscure details we need. For example, compare the tag name 'GPSLatitude' to the description 'GPS Latitude'. We can use the tag name, but not the description to extract the latitude value from our files.
-g2, organizes output by category. All location specific information is grouped together, as is all information related to the camera, date and time tags, etc. You may feel, as I do, that this grouping makes it easier to examine the output. Also, this organization is more likely to reflect the grouping of field names used by your photo management application.
If you prefer to save the output to a file, you can add ExifTool's -w option with a file extension.
$ exiftool -f -s -g2 -w txt path/image.jpg
This command will produce the same result but write the output to the file 'image.txt' in the current directory; again, where 'image.jpg' is the name of the image file. The -w option appends the named extension to the image file's basename, creates a new file with that name, and sets the new file as the destination for output.
The tag names that correspond to the list of Aperture fields presented above are:
metadata tag name
Aperture field label
Image Date
Country Name
Pixel Width
Pixel Height
Section 4: Making Photos Available to Google Earth
We will use some of the metadata tags from our image files to locate our photos on the map (e.g. GPSLatitude, GPSLongitude), and others to describe the photos. For example, we will include the value of the People tag in the information window that accompanies each marker to identify friends and family who appear in the associated photo.
Because we want to display and link to photos on the map, not just indicate their position, we need to include references to the location of our image files on a publicly accessible web server. You have some choice about how to do this, but for the implementation described here we will (1) Display a thumbnail in the info window of each map marker and (2) include a link to the details page for the image in a gallery created in our photo management app.
When a visitor clicks on a map marker they will see a thumbnail photo along with other brief descriptive information. Clicking a link included as part of the description will open the viewer's web browser to a page displaying a large size image and additional details. Furthermore, because the page is part of a gallery, viewers can jump to an index page and step forward and back through the complete collection. This is a complementary way to browse our photos. Taking this one step further, we could add a comments section to the gallery pages or replace the gallery altogether, instead choosing to display each photo as a weblog post for example.
The structure of the gallery created from my photo app is as follows...
/ (the root of the gallery directory)
The application creates a root directory containing the complete gallery. Assuming we do not want to make any manual changes to the finished site, publishing is as easy as copying the entire directory to a location within the web server's document root.
assets/: Is a subfolder containing files related to the theme itself. We don't need to concern ourselves with this sub-directory.
catalog/: Contains a single catalog.plist file which is specific to Aperture and not relevant to this discussion.
pictures/: Contains the large size images included on the detail gallery pages.
thumbnails/: This subfolder contains the thumbnail images corresponding to the large size images in pictures/.
Finally, there are a number of files at the root of the gallery. These include index pages and files named 'large-n.html', where n is a number starting at 1 and increasing sequentially e.g. large-1.html, large-2.html, large-3.html, ...
The index files are the index pages of our gallery. The number of index pages generated will be dictated by the number of image files in the gallery, as well as the gallery's layout and design. index.html is always the first gallery page.
The large-n.html files are the details pages of our gallery. Each page features an individual photo with links to the previous and next photos in sequence and a link back to the index. You can see the gallery I have created for this tutorial here:
If you take the time to look through the gallery, maybe you can appreciate the value of viewing these photos on a map. Web-based photo galleries like this one are nice enough, but the photos are more interesting when viewed in some meaningful context.
There are a couple of things to notice about this gallery.
Firstly, picture-1.jpg, thumb-1.jpg, and large-1.html all refer to the same image. So if we pick one of the three files we can easily predict the names of the other two. This relationship will be useful when it comes to writing our script.
There is another important issue I need to call to your attention because it will not be apparent from looking only at the gallery structure. Aperture has renamed all of my photos in the process of exporting them.
The name of the original file from which picture-1.jpg was generated (as well as large-1.html and thumb-1.jpg) is 'IMG_0277.JPG', which is the filename produced by my camera. Because I want to link to these gallery files, not my original photos which will stay safely tucked away on a local drive, I must run the script against the photos in the gallery. I cannot run it against the original image files because the filenames referenced in the output are unrelated to the files in the gallery.
If my photo management app provided me the option of preserving the original filenames for the corresponding photos in the gallery, then I could run the script against the original image files or the gallery photos because all of the filenames would be consistent, but this is not the case. I don't have a problem as long as I run the script on the exported photos.
However, if I'm running the script against the photos in the web gallery, either the pictures or thumbnail images must contain the same metadata as the original image files. Aperture preserves the metadata in both. Your application may not.
A simple, dependable way to confirm that the metadata is present in the gallery files is to run ExifTool first against the original file and then the same photo in the pictures/ and thumbnails/ directories in the gallery. If ExifTool reports identical metadata, then you will have no trouble using one of pictures/ or thumbnails/ as your source directory. If the metadata is not present or not complete in the gallery files, you may need to use the script on your original image files. As has already been explained, this isn't a problem unless the gallery produces filenames that are inconsistent with the original filenames, as Aperture does. In this case you have a problem. You won't be able to run the script on the original image files because of the naming issue or on the gallery photos because they don't contain metadata.
Make sure that you understand this point.
If you find yourself in this situation, then your best bet is to generate files to use with your maps from your original photos in some other way, bypassing your photo management app's web gallery features altogether in favor of a solution that preserves the filenames, the metadata, or both. There is another option which involves setting up a relationship between the names of the original files and the gallery filenames. This tutorial does not include details about how to set up this association.
Finally, keep in mind that though we've looked at the structure of a gallery generated by Aperture, virtually all photo management apps produce galleries with a similar structure. Regardless of the application used, you should find:
- A group of html files including index and details pages
- A folder of large size image files
- A folder of thumbnails
Once you have identified the structure used by your application, as we have done here, it will be a simple task to translate these instructions.
Section 5: Referencing Files Over the Internet
Now we can talk about how to reference these files and gallery pages so that we can create a script to generate a KML file that includes these references.
When we identify a file over the internet, it is not enough to use the filename, e.g. 'thumb-1.jpg', or even the absolute and relative path to the file on the local computer. In fact these paths are most likely not valid as far as your web server is concerned. Instead we need to know how to reference our files such that they can be accessed over the global internet, and the web more specifically. In other words, we need to be able to generate a URL (Uniform Resource Locator) which unambiguously describes the location of our files. The formal details of exactly what comprises a URL5; are more complicated than may be obvious at first, but most of us are familiar with the typical URL, like this one:
which describes the location of a document titled "Universal Resource Identifiers in WWW" that just so happens to define the formal details of what comprises a URL.
This portion of the address is enough to describe the location of a particular web server over the public internet. In fact it does a little more than just specify the location of a machine. The http:// portion is called the scheme and it identifies a particular protocol (i.e. a set of rules governing communication) and a related application, namely the web. What I just said isn't quite correct; at one time, HTTP was used exclusively by the web, but that's no longer true. Many internet-based applications use the protocol because the popularity of the web ensures that data sent via HTTP isn't blocked or otherwise disrupted. You may not be accustomed to thinking of it as such, but the web itself is a highly-distributed, network-based application.
This portion of the address specifies a directory on the server. It is equivalent to an absolute path on your local computer. The leading forward slash is the root of the web server's public document directory. Assuming no trickiness on the part of the server, all content lives under the document root.
This tells us that rfc/ is a sub-directory contained within the document root. Though this directory happens to be located immediately under the root, this certainly need not be the case. In fact these paths can get quite long.
We have now discussed all of the URL except for:
which is the name of a specific file. The filename is no different than the filenames on your local computer. Let's manually construct a path to one of the large-n.html pages of the gallery we have created.
The address of my server is robreed.net, so I know that the beginning of my URL will be:
I keep all of my galleries together within a photos/ directory, which is contained in the document root.
Within photos/, each gallery is given its own folder. The name of the folder I have created for this tutorial is 'tutorial_gallery'. Putting this all together, the following URL brings me to the root of my photo gallery:
We've already gone over the directory structure of the gallery, so it should make sense you to that when referring to the 'large-1.html' detail page, the complete URL will be:
the URL of the image that corresponds to that detail page is:
and the thumbnail can be found at:
Notice that the address of the gallery is shared among all of these resources. Also, notice that resources of each type (e.g. the large images, thumbnails, and html pages) share a more specific address with files of that same type.
If we use the term 'base address' to refer to the shared portions of these URLs, then we can talk about several significant base addresses:
The gallery base address: http://robreed.net/photos/tutorial_gallery/
The html pages base address: http://robreed.net/photos/tutorial_gallery/
The images base address: http://robreed.net/photos/tutorial_gallery/pictures/
The thumbnails base address: http://robreed.net/photos/tutorial_gallery/thumbnails/
Note that given the structure of this particular gallery, the html pages base address and the gallery base address are identical. This need not be the case, and may not be for the gallery produced by your application.
We can hard-code the base addresses into our script. For each photo, we need only append the associated filename to construct valid URLs to any of these resources. As the script runs, it will have access to the name of the file that it is currently evaluating, and so it will be a simple matter to generate the references we need as we go.
At this point we have discussed almost everything we need to put together our script. We have:
- Created a gallery at our server, which includes our photos with metadata in tow
- Identified all of the metadata tags we need to extract from our photos with the script and the corresponding field names in our photo management application
- Determined all of the base addresses we need to generate references to our image files
Section 6: KML
The last thing we need to understand is the format of the KML files we want to produce.
We've already looked at a fragment of KML. The full details can be found on Google's KML documentation pages , which include samples, tutorials and a complete reference for the format.
A quick look at the reference is enough to see that the language includes many elements and attributes, the majority of which we will not be including in our files. That statement correctly implies it is not necessary for every KML file to include all elements and attributes. The converse however is not true, which is to say that every element and attribute contained in any KML file must be a part of the standard.
A small subset of KML will get us most, if not all, of what you will typically see in Google Earth from other applications.
Many of the features we will not be using deal with aspects of the language that are either:
- Not relevant to this project, e.g. ground overlays (GroundOverlay) which "draw an image overlay draped onto the terrain"
- Minute details for which the default values are sensible
There is no need to feel shortchanged because we are covering only a subset of the language. With the basic structure in place and a solid understanding of how to script the generation of KML, you will be able to extend the project to include any of the other components of the language as you see fit.
The structure of our KML file is as follows:
1. <?xml version="1.0" encoding="UTF-8"?>
2. <kml xmlns="http://earth.google.com/kml/2.1">
3. <Document>
4. <Folder>
5. <name>$folder_name</name>
6. <description>$folder_description</description>
7. <Placemark>
8. <name>$placemark_name</name>
9. <Snippet maxLines="1">
10. $placemark_snippet
11. </Snippet>
12. <description><![CDATA[
13. $placemark_description
14. ]]></description>
15. <Point>
16. <coordinates>$longitude,$latitude
17. </Point>
18. </Placemark>
19. </Folder>
20. </Document>
21. </kml>
Line 1: XML header
Every valid KML file must start with this line and nothing else is allowed to appear before it. As I've already mentioned, KML is an XML-based language and XML requires this header.
Line 2: Namespace declaration
More specifically this is the KML namespace declaration, and it is another formality. The value of the xmlns attribute must be a URI referencing a resource that identifies elements and attributes which are valid under the language. Remember that KML is one of many XML based languages, each with its own vocabulary. Making namespaces unique to each language avoids the obvious problems that would occur if all languages were required to pull from a common pool of identifiers. In such a scheme all identifiers would need to be unique among all XML based languages, —a situation which would quickly prove unworkable.
The first two lines are strictly boilerplate. They are required and will be identical in every KML file you produce. They change only when the language itself is modified.
Line 3: <Document> is a container element representing the KML file itself. If we do not explicitly name the document by including a name element then Google Earth will use the name of the KML file as the Document element <name>.
The Document container will appear on the Google Earth 'Sidebar' within the 'Places' panel. Optionally we can control whether the container is closed or open by default. (This setting can be toggled in Google Earth using a typical disclosure triangle.) There are many other elements and attributes that can be applied to the Document element. Refer to the KML Reference for the full details.
Line 4: <Folder> is another container element. The files we produce will include a single <Folder> containing all of our Placemarks, where each Placemark represents a single image. We could create multiple Folder elements to group our Placemarks according to some significant criteria. Think of the Folder element as being similar to your operating system's concept of a folder.
At this point, note the structure of the fragment. The majority of it is contained within the Folder element. Folder, in turn, is an element of Document which is itself within the <kml> container. It should make sense that everything in the file that is considered part of the language must be contained within the kml element.
From the KML reference:
A Folder is used to arrange other Features hierarchically (Folders, Placemarks, NetworkLinks, or Overlays). A Feature is visible only if it and all its ancestors are visible.
Line 5: The name element identifies an object, in this case the Folder object. The text that appears between the name tags can be any plain text that will serve as an appropriate label.
Line 6: <description> is any text that seems to adequately describe the object.
The description element supports both plain text and a subset of HTML. We'll consider issues related to using HTML in <description> at the discussion of Placemark, lines 12 - 14.
Lines 7 - 17 define a <Placemark> element.
Note that Placemark contains a number of elements that also appear in Folder, including <name> (line 8), and <description> (lines 12 - 14). These elements serve the same purpose for Placemark as they do for the Folder element, but of course they refer to a different object.
I've said that <description> can include a subset of HTML in addition to plain text. Under XML, some characters have special meaning. You may need to use these characters as part of the HTML included in your descriptions. Angle brackets (<, >) for example surround tag names in HTML, but serve a similar purpose in XML. When they are used strictly as part of the content, we want the XML parser to ignore these characters.
We can accomplish this a few different ways:
We can use entity references, either numeric character references or character entity references, to indicate that the symbol appears as part of the data and should not be treated as part of the syntax of the language. The character '<', which is required to include an image as part of the description (something we will be doing), (e.g. <img src=... />) can safely be included as the character entity reference '<' or the numeric character reference '<'.
The character entity references may be easier to remember and recognize on sight but are limited to the small subset of characters for which they have been defined. The numeric references on the other hand can specify any ASCII character. Of the two types, numeric character references should be preferred. There are also Unicode entity references which can specify any character at all.
In the simple case of embedding short bits of HTML in KML descriptions, we can avoid the complication of these references altogether by enclosing the entire description in a CDATA6 element, which instructs the XML parser to ignore any special characters that appear until the end of the block set off by the CDATA tags.
Notice the string '<![CDATA[' immediately after the opening <description> tag within <Placemark>, and the string ]]> immediately before the closing </description> tag. If we simply place all of our HTML and plain text between those two strings, it will all be ignored by the parser and we are not required to deal with special characters individually. This is how we'll handle the issue.
Lines 9 - 11: <Snippet>
The KML reference does a good job of clearly describing this element.
From the KML reference:
In Google Earth, this description is displayed in the Places panel under the name of the feature. If a Snippet is not supplied, the first two lines of the <description> are used. In Google Earth, if a Placemark contains both a description and a Snippet, the <Snippet> appears beneath the Placemark in the Places panel, and the <description> appears in the Placemark's description balloon. This tag does not support HTML markup. <Snippet> has a maxLines attribute, an integer that specifies the maximum number of lines to display. Default for maxLines is 2.
Notice that in the block above at line 9, I have included a 'maxLines' attribute with a value of 1. Of course, you are free to substitute your own value for maxLines, or you can omit the attribute entirely to use the default value.
The only element we have yet to review is <Point>, and again we need only look to the official reference for a nice description.
From the KML reference:
A geographic location defined by longitude, latitude, and (optional) altitude. When a Point is contained by a Placemark, the point itself determines the position of the Placemark's name and icon.
<Point> in turn contains the element <coordinates> which is required.
From the KML reference:
A single tuple consisting of floating point values for longitude, latitude, and altitude (in that order).
The reference also informs us that altitude is optional, and in fact we will not be generating altitude values.
Finally the reference warns:
Do not include spaces between the three values that describe a coordinate.
This seems like an easy mistake to make. We'll need to be careful to avoid it.
There will be a number of <Placemark> elements, one for each of our images.
The question is how to handle these elements. The answer is that we'll treat KML as a 'fill in the blanks' style template. All of the structural and syntactic bits will be hard-coded, e.g. the XML header, namespace declaration, all of the element and attribute labels, and even the whitespace, which is not strictly required but will make it much easier for us to inspect the resulting files in a text editor. These components will form our template.
The blanks are all of the text and html values of the various elements and attributes. We will use variables as place-holders everywhere we need dynamic data, i.e. values that change from one file to the next or one execution of the script to the next.
Take a look at the strings I've used in the block above. $folder_name, $folder_description, $placemark_name, etc. For those of you unfamiliar with Perl, these are all valid variable names chosen to indicate where the variables slot into the structure. These are the same names used in the source file distributed with the tutorial.
Section 7: Introduction to the Code
At this point, having discussed every aspect of the project, we can succinctly describe how to write the code. We'll do this in 3 stages of increasing granularity.
Firstly, we'll finish this tutorial with a natural language walk-through of the execution of the script.
Secondly, if you look at the source file included with the project, you will notice immediately that comments dominate the code. Because instruction is as important an objective as the actual operation of the script, I use comments in the source to provide a running narration. For those of you who find this superabundant level of commenting a distraction, I'm distributing a second copy of the source file with much of the comments removed.
Finally, there is the code itself. After all, source code is nothing more than a rigorously formal set of instructions that describe how to complete a task. Most programs, including this one, are a matter of transforming input in one form to output in another. In this very ge
Section 8: Natural language walk-through
- We need to prime the script by hard-coding some variable assignments. These 'configurable variables' serve the same purpose as the preferences, menus and dialog boxes typical of GUI applications.
Among other values we'll specify:
- The names of the KML output files
- The directory where the script should look for our photos
- and our Google Maps API key
Important: If you haven't yet, now is a perfect time to sign up for a key.
Before running the script, open the source file and look for the 'configurable variables' section of the code. Read through the comments describing each required value, make whatever necessary changes, and save the file.
- We need to create our KML output files.
If there is a problem which prevents the script from writing these files, we can determine that at the beginning of execution before doing any other work.
- The script starts reading from the 'fill in the blanks' template included in the data section of the source file, which is read via the __DATA__ pseudo-filehandle. (See the comments in the source for more information.)
The template looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<Style id="tutorial_custom_icon">
All of the literal text in the template is written directly to the output files.
The term 'literal text' applies to those parts of our template written directly into the source code, or in other words that are not part of the metadata extracted from the image files or computed values.
Notice that there are a number of placeholder strings in the template:
Because these placeholders are all unique strings in the template we can attempt to match against of them as we read each line and, wherever a match succeeds, substitute the current value of the appropriate variable for the placeholder. Note that some of these are from the configurable variables section of the file while others are values set dynamically during execution.
We could simply include the values from the configurable variables section in the template rather than assigning these values to variables, and then substituting the values for placeholders as described.
Handling it the way it has been presented here allows us to group all of the values we must set manually together in one small section at the top. This is considered to be preferable to scattering these values throughout the source because it makes it easier to configure the script and maintain the code. For example, it minimizes the chance that we'll break something by making an inadvertent change when we only intended to update one of these values. There are a number of other benefits as well, including these commonly noted advantages:
- These values are essentially options or directives we use to modify the behavior of the script. Grouping them together makes it more efficient to use our little command line executable, just as well organized menus make it easier to work with a GUI-based app.
- Grouping these values together makes it easier to examine them.
- Because the values are defined once and stored in variables, we can repeatedly use the same values at more than one point in the code without retyping them. Reusing values whenever possible, rather than recreating them, significantly decreases the likelihood of a typo or some other careless mistake breaking the execution of the program or ruining our output.
- Defining values only once avoids a common problem where two or more independent values that are intended to be identical get out of sync when the value is not updated everywhere it is used.
When we encounter the Placemarks section of the KML template (i.e. the string !placemarks_go_here!) we need to append one Placemark element for each of our image files.
The Perl module File::Find, which is part of the standard distribution, defines a number of functions for traversing a filesystem hierarchy starting at a specified root. One of these functions, find(), does a depth-first search of the directory tree, running a routine we provide it against every item found, where an item is any of the possible filesystem entry types (these vary among platforms but always include files and directories among others).
For example, Unix-like operating systems typically allow for seven (7) unique entry types including:
- plain files
- directories
- symbolic links
- named pipes
- block special files
- character special files
- sockets
These different types of entries and the differences among platforms aren't particularly important to us. For our purposes, there are only 2 categories of entries: plain files and everything else. If the item is not a file, we can ignore it regardless of type.
We need to define a routine that can be run against each item found. We provide find() a reference to the routine and a starting location and it arranges for the routine to run repeatedly, once for each item in the directory tree starting at the root.
From the documentation for File::Find
find(&wanted, @directories_to_search);
sub wanted { ... }
"find()" does a depth-first search over the given @directories in the order they are given.For each file or directory found, it calls the &wanted subroutine.Additionally, for each directory found, it will "chdir()" into that directory and continue the search, invoking the &wanted function on each file or subdirectory in the directory.
The wanted function takes no argumentsbut rather does its work through a collection of variables.
$File::Find::dir is the current directory name, $_ is the current filename within that directory, $File::Find::name is the complete pathname to the file.Don't modify these variables.
The documentation confirms that we need to supply find() a reference to a function, &wanted, and a list of directories to search, @directories_to_search.
@directories_to_search is easy enough, we want to search the folder containing our geotagged image files. This is the value of one of our configurable variables ($photos_dir).
Let's describe the routine that find() will run against each item in $photos_dir. Make sure you understand that the routine should be designed to run against only one item. If there are many items, find() will call the routine many times, but that is irrelevant as far as the design of the routine is concerned.
For a single item:
- First, the routine runs a series of tests to determine if it is:
- a file
- the appropriate type of file
- and readable
The second test will make a determination based on the filename extension. As written, the script considers any file that ends in .jpg or .jpeg (case insensitive) a valid file type. You can expand this list to include extensions for other types of image files or alternative extensions for jpeg files.
If the item fails any of these tests then we immediately return from our routine, essentially skipping it.
- If the item passes all of the tests, we use ExifTool to extract from the image's metadata only those tag values we're interested in (detailed above).
- Next check for the 'GPSLatitude' and 'GPSLongitude' tags among the list returned from ExifTool. If there are not defined values for these tags then the tag names will not be included among the list returned. Though the item may be a valid image file, without coordinate data we can't know where to position a marker representing this photo on a map, so there's nothing we can do with it in our mapping application. We have no choice but to skip it.
Note that any photo for which there is no coordinate data will be missing from our output files.
- Assuming we have at least the two tags 'GPSLatitude' and 'GPSLongitude', we use the tag values to build a Placemark element for the image and write the element to output.
We assemble a
<description> element for the Placemark by combining several of the tag values.
We can account for optional tags, which may or may not have been populated in the metadata for the image (the tag People for example) by determining if ExifTool was able to find values for the associated tag names. If no value was found, because the tag was not used, the corresponding variable will be undefined.
The Placemark description for each of our image files can be illustrated by the following block, which is another template:
<li>People: $People</li>
<li>Event: $Event</li>
<li>Location: $Location</li>
<li>City: $City</li>
<li>State: $State</li>
<li>Country: $Country</li>
<li>Date: $DateTimeOriginal</li>
Variables are replaced by tag values extracted from the current image file. If one or more of the variables is undefined, we simply do not include the entire line.
$thumbnail_img is a complete URL to a thumbnail which will be included in the description via the <img> tag's src attribute, e.g.
<img src="$thumbnail_img" />
$image_link is a complete URL to the gallery detail page featuring the photo. We include a link to the page in the description, e.g.
<a href="$image_link">Gallery details page for this image</a>
As we have just seen, among the metadata tags we want to extract are the regional tags 'City', 'State/Province' and 'Country'. Assuming values for these tags are defined, we will include the information as part of the description in our <placemark>, which means we will see it displayed in the information window when we click the marker representing this image on the map.
We also use these tags to assist us with clustering in our Google Maps application and as a first step to implementing a feature called 'Regions' in Google Earth (more on the topic of Regions later).
Throughout the tutorial I've said that we will be generating more than one output file, but we haven't identified what these files are until now.
By default, the names of the output files generated in the script accompanying the tutorial are:
- photos.kml
- cities.kml
- states.kml
- countries.kml
photos.kml is the only file of interest as far as this part of the tutorial is concerned. It is the output file we've been discussing to this point. This is the file that includes one <placemark> for each of our geotagged image files.
What are the others?
In the source we declare the three hashes:
%known_cities%known_ states%known_countries
These hashes will contain one key for each unique region represented among the geotagged images (i.e. one key in the appropriately named hash for each city, state, and country represented).
The purpose of these hashes is to enable clustering of markers on our maps around large, well-defined geographical areas at lower zoom levels.
What is clustering?
Until we are above some threshold level, we will not be able to distinguish between markers for photos first within the same country, then state/province, and finally city, assuming we have more than one photo for the region. In these cases we create a single marker at the center of the region to indicate that there are photos available which cannot be displayed at the current zoom level.
- Before we return from the routine, we check the hashes to see if the keys corresponding to the tag values from the current image file already exist. If they don't, we add them.
For example, if the current image file is a photo of Boston, Massachusetts (USA), the following is a partial list of tag values from ExifTool:
City: "Boston"
State: "MA"
Country: "USA"
Let's say that the script has already come across a photo of someplace in the United States. If that's the case, then the key "USA" will already exist in the %known_countries hash. We don't have to add it again.
If we've also seen at least one photo taken somewhere in Massachusetts, then the key "MA, USA" will exist in %known_states; but let's say this is the first photo of Boston, Massachusetts. Then the key "Boston, MA" will not exist in %known_cities, so it will be added to the hash.
If this is all a little unclear, it may help to look at the source file.
After all items have been evaluated, find() returns. At this point in execution, we've generated a Placemark element for each image, and finished populating the regional hashes.
- For each key in the regional hashes, the script creates a Placemark element in one of cities.kml, states.kml or countries.kml (these are the default output filenames). For example, for every key in the %known_countries hash, a Placemark is created in the countries.kml file.
There are a couple of important differences between photos.kml and these regional files.
- There will be only one Placemark element for each unique regional location. So if we have 100 image files and all of them are photos of Boston, MA, then we will have a single Placemark element in each of cities.kml, states.kml, and countries.kml - not 100 identical Placemark elements in each.
- Because these Placemarks represent regions, not photos, there is no metadata for us to work with. How do we get a coordinate pair for each city, state, and country?
We have two options.
The Google Maps API includes a geocoder we can use. From the documentation we have this definition of geocoding:
Geocoding is the process of converting addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates (like latitude 37.423021 and longitude -122.083739), which you can use to place markers or position the map based on street addresses in your database or addresses supplied by users.
We can pass the geocoder any one of our hash keys and it will return the geographic coordinates representing the center of the named region.
The problem is that it returns coordinates for what I'll call the 'computed center' of the region, which is not always what we want. For example, the following is a link to maps.google.com identifying the computed center of Massachusetts (my home state).
The arrow identifies the computed center of the state as reported by Google's geocoder, which seems to indicate that the center is along the southern border. This makes sense when you consider that Massachusetts includes Cape Cod and Nantucket, which are much further southeast than the rest of the state.
If you aren't bothered by these odd-looking but technically accurate computed coordinates, then Google's geocoder may be all you need. Also, if your regions are regularly shaped then this issues won't be apparent to you.
Alternatively, you could build a set of associations between region names and the geographic coordinates you want to represent these places.
As written, the script allows you to do both. In addition to using the geocoder, you can manually associate regional locations with specific coordinates in the configurable variables section of the code. Instructions are included in the source file itself. If you have manually placed a particular region, then it will use your coordinates, otherwise it will use Google's geocoder.
Note: Use of the geocoder here is the reason that you must include a Google Maps API key in the script.
These regional places are useful for clustering with Google Maps and Google Earth. Clustering in Google Earth requires the use of Regions which are not implemented in this tutorial. The topic of clustering will come up again in the Google Maps portion of the project.
- After generating all of our Placemark elements, there are a couple of lines from the KML template at DATA that must still to be appended to the output before we're finished. These are nothing more than closing tags for the <Folder>, <Document> and <kml> elements and can be written directly from our template to the the output files.
- At the end of execution we print a few statistics that have been collected throughout execution to help users identify problems, or confirm that the script ran as expected. These are simple counters or based on simple counters, but are useful nonetheless.
At the end of execution we have generated our KML files:
photos.kml, cities.kml, states.kml, countries.kml
Of primary interest is photos.kml.
Because we're not dealing with Regions for clustering in Google Earth, the regional kml files aren't useful for this part of the tutorial, but don't delete them because we will be using clustering in Google Maps. Should we decide to use Regions in the future, implementing the feature will be a much simpler proposition than it would be otherwise because we've already done some of the work involved.
Section 9: Finishing up
You can, and probably should, validate your KML files to ensure that they adhere to the standard. This doesn't take a long time and it's easy to do. If you've uploaded your files to a publicly accessible web server, visit the Feed Validator.
Once at the site, type the complete URL of your KML file(s), one at a time, into the text entry field and click the validate button.
A note about the results:
The validator makes a distinction between warnings and errors.
If your file conforms to the standard, but the validator has some suggestions for improving it you'll see the message:
This feed is valid, but may cause problems for some users.
We recommend fixing these problems.
If you scroll down the page you will see a message confirming that the feed has validated.
If there are actually errors in the file it will not validate, and you will see the message:
This feed does not validate.
In either case, the validator will identify the lines in the file that produced the messages as well as an attempted explanation of the issue.
Once your feed validates, all that's left to do is enjoy browsing and sharing your photos.
Section 10: Sharing KML Files
- You can open the KML files locally.
Doubling-clicking photos.kml should open Google Earth. Alternatively, launch Google Earth, choose 'Open...' from the 'Edit' menu and use the standard dialog box to navigate the filesystem to your photos.kml file.
- You can share the file via email.
Because the files contain only text, you can depend on file sizes being relatively small. Remember that images are referenced in the file via URL not included directly.
- If you upload the file to a public web server, something you'll want to do in preparation for the Google Maps portion of the project, then others can access your images from within Google Earth by adding a Network Link.
However you choose to share the KML file, you can select the folder containing all of your photo markers in Google Earth's Places panel and 'tour' your photos. A tour moves from one marker to the next on the map, pausing for a short amount of time at each and (optionally) displaying the marker's information window.
Finally, and as a preview of what we'll be doing next, you can display your KML file in Google Maps in either of two ways:
You can visit the Google Maps site at maps.google.com and type the full URL to your photos.kml file into the search field on the page.
Equivalently, you can pass the URL for the photos.kml file as the value to that application's 'q' parameter.
For example, the KML file I've created for this project is located at:
I can display the data from the file in Google Maps at:
We can't change anything about the Google designed page, which works well for only small numbers of images. If you had hundreds of image files on the other hand, the 'Contents' list in the sidebar on the page would be very long and unwieldy. Also, we cannot incorporate clustering or other features available to us through the API.
Take a look at my kml file and you'll see the problem that clustering solves on display around the area of Boston, MA, where the majority of the 113 photos in the collection were taken. As you zoom in, the space between the markers on the map increases. At some point, you will be able to clearly distinguish between all of them, but at the default zoom level, there are a jumble of indistinguishable, overlapping icons.
Limitations notwithstanding using Google Maps and KML in this way is useful in its own right and a good demonstration of what's possible.
Section 11: Next Steps
What could be done to improve on this script?
The next topic you should familiarize yourself with related to Google Earth is 'Regions', which make it possible to efficiently work with very large datasets in Google Earth, even when publishing data over a network.
Regions define areas in Google Earth in terms of a 'bounding box' and 'levels of detail'.
The bounding box defines the northern, southern, eastern, and western boundaries of the user's current view of the Google Earth map (and also possibly min and max altitude values if appropriate, for example when working with 3D objects).
Level of detail describes the number of pixels the Region currently occupies on screen. Keep in mind that even a large area (large in terms of coordinate boundaries) may occupy only a small portion of the map at low zoom levels. Of course the reverse is also true, i.e. very small geographic areas may fill a large portion of the display at the highest zoom levels. Or we can say that at high zoom levels the resolution of the view is much greater than it is at the lowest levels. As a result of this higher resolution, more markers can be distinguished on the map but the field of view is decreased. At lower resolutions adding a lot of detail to the map, i.e. many Placemarks, only results in overlapping, indistinguishable markers. Google Earth and your computer must work harder to display these Placemarks. In the case of Network Links, all of this data must be transmitted over relatively slow connections, significantly reducing the performance of the application and detracting from the appeal of using Google Earth as a solution for sharing your photos.
This discussion may sound confusing the first time you read it. Suffice it to say that it makes little sense to produce markers for photos on your map that are not visible to your audience because they exist outside the current view or because they are obscured by other markers. Regions solve these issues by ignoring data that is either outside of the current bounds of the map, or indistinguishable because of the current resolution. While we are dealing with only hundreds or thousands of images, this isn't necessarily a significant concern. At the point when we are sharing tens of thousands of photos, or perhaps hundreds of megabytes worth of data, Regions are critically important.
Because the use of Regions is not necessary given the scope of this project (hundreds of photos) I'll not pursue this topic further. I can say that you will be able to incorporate Regions into the rest of this project if you choose to do so. Nothing that we do here precludes the use of Regions or complicates their use.
Note that we will be implementing a similar feature in Google Maps, because the issue of inefficiency is a problem with far fewer markers. Google provides a 'marker manager' that is similar in functionality to the Regions feature in Google Earth. Allowing the application to ignore photos outside the current view and 'cluster' (i.e. reduce the number of markers generated) in response to the resolution of the map at various zoom levels. The discussion of the marker manager should help you with the concept of Regions.
Section 12: Conclusion
We've finally come to the end of the Google Earth project, which is actually the first half of a 2-part tutorial. If you haven't looked at the source code yet, now is the time.
If you followed along with the tutorial, the code will seem very familiar to you. Also, if you have some questions after reading through the tutorial, the extensive comments in the source should help. If you've successfully generated your KML files, congratulations. If you're still working on it, and especially if you're having some trouble, I would encourage you to keep at it. Maybe take a break and come back. It's always been surprising to me just how much clearer a problem becomes after spending some time away from it doing anything else.
I hope you continue on to the second project, where we look at building a Google Map from the KML files that we've generated. In the process we'll cover the Google Maps API, Javascript, object models, the DOM, and we'll talk a little bit about XHTML.
See you there.
>> Continue Reading Google Earth, Google Maps and Your Photos: a Tutorial Part II
1 Exif: (E)(x)changeable (i)mage (f)ile format. EXIF.org is an unofficial site that at least links to the specifications. See the appendix for more information about the Exif standard.
2 (I)nternational (P)ress (T)elecommunications (C)ouncil. See the IPTC entry at Wikipedia for more information: http://en.wikipedia.org/wiki/IPTC
3 XMP home at adobe.com: http://www.adobe.com/products/xmp/index.html
4 The ExifTool homepage at http://www.sno.phy.queensu.ca/~phil/exiftool/ is the best reference for the project. Other than a tutorial like this one, you shouldn't need another resource.
5 RFC 1630: http://www.ietf.org/rfc/rfc1630.txt
6 The name CDATA is formed from the phrase 'Character DATA'
Rob Reed has over 10 years experience in the IT industry. He has held positions as the Director of Technology, IT Director, and Research and Development Technical Lead for various firms. Currently, he is an independent consultant and is pursuing a graduate degree in Computer Science at Tufts University (Medford, MA). His thesis work looks at issues of semantic information management. He is also interested in the topics of computing platforms, network and systems security, programming languages, and development. He maintains a weblog at http://robreed.net/weblog. He can be reached at firstname.lastname@example.com.


text:
Prime Minister Narendra Modi deserves thumping congratulations for demonetizing notes of Rs 500 and Rs 1000 denominations. This will hit hard at the fake note rackets being run by terrorists, and the large amount of monies stashed away by politicians, government officials and hawala operators. This move will provide much relief to honest taxpayers. Businesses in the country make large transactions in cash. They do not pay taxes on these transactions. This leads to large loss of revenue to the Government.
Development of capacities in an environment of shrinking opportunities acts like fuel in fire. The competition among the unemployed for the limited number of jobs becomes more intense, explains Dr Bharat Jhunjhunwala
Shoppers throng Malls during the new year. Shops offer discounts to attract them to the Malls. People compete with neighbours in doing more shopping. No wonder, the International Council of Shopping Centers is upbeat. A research paper published by the Council states: Mall tenants are currently enjoying industry-leading sales, operating margins and after-tax profit growth. Mall rents have also grown. The situation in India does not seem to follow this bright prognosis, however. Leaving aside a few malls of Gurgaon, the picture is downbeat.
The Government has certainly made some progress in the alleviation of poverty. Programs like Employment Guarantee, subsidized food grains to BPL families and loan waiver for farmers have provided relief to the poorest people. But this is not helping establish peace in the countryside. Maoist activities are increasing. The reason may lie in the huge increase in inequality. Businesses are earning huge profits. Results of top companies indicate an increase in profits of about 28 percent against increase in sales of 2 percent.
The European economic crisis not only persists but continues to get deeper despite the efforts of International Monetary Fund, European Central Bank and other multilateral agencies. Reason is a wrong diagnosis of the disease. It is believed that the main problem of Europe is the disconnect between monetary and fiscal policies. Monetary policies such as interest rates and liquidity in the money market of all members of the Eurozone are determined by the European Central Bank (ECB).
The Mullaperiyar Dam was built about 100 years ago in Tamil Nadu on the border of Kerala. The dam has become weak since then. There is some leakage of water. People of Kerala apprehend that it may break some day. In such an event large amounts of water and sediments will flow through Kerala and destroy fields, villages and cities. People of Kerala are demanding that the dam be dismantled and a new safe dam be built. The Government of Kerala is willing to pay the cost of reconstruction. People of Tamil Nadu, however, are not convinced.
Black money is unquestionably harmful for the economy.
Consumption, the base of modern economics, does not necessarily lead low welfare of masses.
Dr Bharat Jhunjhunwala
Dr Bharat Jhunjhunwala

subset: commoncrawl


text:
Ask a Law Question, Get an Answer ASAP!
At time of divorce he was living in Poland. I've had no contact at all. He is a captain on sea-going tankers, so could be living anywhere. I would love to ask him but only know his bank account was with Lloyds in Helston, cornwall.
Do you think that you can find his address?
No, I would not know where to start! I only know that he was on a course run by Anglo Eastern crew management in Sept. 12. That is only because he put a comment on- line. Don't know where it was or if he was working on the course or just a participant. Sorry.
Don't worry, that is why weare here, to assist you with problems like this.
This firm will do no find nofee (I have used them on many occasions) for 50 quid plus VAT. http://www.ccsformations.co.uk/Tracing-25-c.html
They also do internationalsearches for under £150, but from what I remember, it is not no find no fee.
The only one person theyfailed to find for me was someone who had deliberately covered his tracks whichappears not to be the case here.
Armed with his address, youcan make an application to court to enforce the judgement, although if he isliving in Poland, you are faced with enforcing the English order in a Polishcourt and will need a Polish Lawyer to do that for you.
If the tracing agency fails tofind him, you can make an application to court for an order to the bank to makethem give you his address for the purpose of enforcing the order.
Can I help further?Please bear with me today because I will beonline and off-line.Please don't forget to positively rate my answer service (even if it was notwhat you wanted to hear) and I will follow up any further points you raise forfree.If you don't rate it positively, then the site keep your deposit and I get 0for my time. It is imperative that you give my answer a positive rating. Itdoesn't give me "a pat on the head", "good boy" (like ebay), it is mylivelihood!If in ratings you feel that you expected more or it only helped a little,please ask me for further info before rating me negatively otherwise I don'tget paid at all for my time and answer. The thread remains open.Thank you.
Thanks for that. Have phoned person on that link you gave me... he says, for data protection, he can only act for me if a solicitor, ie.you!, act on my behalf and instruct him. Thgen he's happy to take it on. So what do I do now?
I am afraid that we are unableto take instructions on here, so you need to find a local solicitor who willdeal with it for you.
If your husband is in Poland,you are going to need one in any event
No, only the name of the company running the course he was present at in September 2012..... Anglo Eastern Crew Management.
No assets in this country that I am aware of. No reason to think the bank account is closed...... I do know the account no. etc. Also, that he has a good pension with BP. Sorry, not very helpful, but you can see why I'm frustrated and don't know where to begin!
No, not that I know of. He was 56 in October.
Thanks for your help.


text:
[ Printer Friendly Version ] [ Report Abuse ]
Chapter 50 : Chapter 50 - No Turning Back
|Rating: 15+
|Chapter Reviews: 81
Background: Font color:
OMG... I am really really sorry!!!!!!!!!! I would have updated sooner! but I got sitract with school and stuff.. and finally i finished it!! The chapter! the one and only LAST chapter!!! i cant beleive 50 chapters later and almost 1000 reviews... i ahven finally finished! i think i'm going to cry! hehe nah... well that is the good news.. the bad news is, i am not going to write a sequel. well not yet that is, I am soon going to write another L/J story and one of my own hehe.. so jsut be waiting for them. Also after I have read HBP there will probably be a sequel to that one too. thanx for all your help everyone! I lvoe you!!! :D
Lotsa love Iced_Cherriez
�Tonks! Remus!� Harry shouted as they entered the huge cave. (A/N It should have been cave, not cage, in the last chapter)
They were hanging in a metal cage, above them, looking as if they were asleep.
�Harry? Is that you?� Remus asked faintly as he opened his eyes a portion.
�Remus! It�s me! We have to get out of here! Now! Voldemort - He said-� But Harry was cut off.
�It�s a trap Harry! You have to leave!� Tonks shouted and her voice echoed.
�I�m not leaving you!� He shouted, small tears forming in his eyes. �Not now, not ever!� He turned to face the others.
�Everyone! I need you to go get the order, tell them to come here.� He lectured the group
�But Harry! We want to fight!� Ginny complained and shook her head.
�No Ginny, there will be no fight! I just need to order to find out where we are and help with Remus and Tonks. Please go!� He ordered and even without his powers working he looked menacing and angry.
The others cringed and nodded slowly. Harry pulled out his wand and picked up a rock off the ground.
�Portus� He whispered. The rock shone blue and he handed it to the others. �Everyone, touch it, now� Harry watched as everyone placed a finger on the rock.
As they all did and the countdown began, Harry smiled secretly to himself, grateful that they were safe. If there was a fight, the members of the order would see that they didn�t come back, so nothing would happen to them.
Even though Harry hid his smile, there was still one person who saw it. This person took their hand away from the rock at the last minute, watching Harry turn away.
Harry turned from the others as he saw them disappear and started for the centre. He looked up to see Tonks and Remus watching him... or were they watching someone else.
Crunch. The rocks on the floor of the cave grounded with the dirt behind him. He spun around, to be face to face with... Neville Longbottom.
�Neville- I thought you went back with the others... Its not safe here and-�
There was a pop from near the cage hanging in the middle. Both boys spun around- to face the most feared wizard of this century. Lord Voldemort.
�Harry Potter... How lucky I must be... to be here with you... It�s been so many years since that night, the night your parents passed.� Harry cringed and walked out into the little light that surrounded the cave.
�Harry! I said it was a trap! You have to get out of here!� Tonks screamed.
�Enough! Be quiet blood traitor!� This was enough to make her silent. �I will deal with you later, after I have been given the chance to succeed with this.� He motioned to Harry. �Harry for so many years I have seeked the death of you... But so many times, I must confess, I have failed. This will not happen tonight!�
�Harry, this is my year! The year I shall rein. Harry Potter, be ready to die!� Voldemort called out in his devil like voice.
Harry turned back to Neville. �Go Neville! Hide!� He yelled.
�Who�s this? Someone else? Who are you, boy!?� The Dark Lord shouted, glaring through his red eyes at the two boys standing at the opposite side of the cave to him. Neville whimpered, but stayed quiet.
�I demand you tell me who you are!� He screamed. Harry looked back at the whimpering boy and felt sad for him.
�He�s just... You don�t have to worry... He�s no one-� But he was cut off.
�I�m not no-one. I�m Neville Longbottom.� The once embarrassed boy voiced as he stepped forward. In the few seconds they had been facing the Dark Lord, Neville seemed to have skipped from a very held back to boy, to someone with utter most confidence.
Voldemort smiled. He knew who Neville was. He could have been the boy the prophecy was talking about.
�It seems I am even luckier. I shall not be defeated tonight! Or ever again! You shall both die tonight!� He howled.
�Avada Kedauvra!�
It seemed like eternity for the spell to reach the other side, and all Harry Potter could do, was watch in horror as the jet of green light sped straight for one of his best friends.
�Neville!� But it was too late. Neville Longbottom was dead before he hit the floor. �NO! Neville!� Harry rushed over to see if the boy could still be alive. It was not possible though.
�Crucio!� Harry heard from behind him, he jumped to the ground, feeling the spell rush rapidly over his messy hair. He watched Neville�s body sadly as he turned to meet his fate.
�What do you mean we can�t come!?� Ron howled over the racket in the living room at number 12.
The four children, minus Neville, had arrived only minutes before, some blood and beaten. They told the order about what had happened, in the quickest way possible and demanded that they helped Harry.
�It�s out of the question Ronald!� Mrs Weasley shouted at him. She glared at the others and most of the wished they hadn�t been born. �What were you thinking, following him!�
�What!? Following Harry?� Ginny asked, confused and unsure of what her mother had meant.
�Yes, exactly. What were you thinking!?� She yelled.
�Mum! We followed him at our own free will. We wanted to help! This is not just about him you know!� Ron yelled.
�Of course it�s not about him. I do not know why he is so court up in destroying You-Know-Who! It�s putting all of you at danger!� Small beads of sweat were forming on her temples, and no one dared argue, except her own son.
�Harry is the only one who can beat Voldemort...� Ron said quietly, not looking up from the ground. Mrs Weasley didn�t say anything, which caused Ron to raise his head in fear.
He looked to see her eyes start to fill with tears as guilt ran through her body.
�That is enough.� Dumbledore said calmly. �You four are not to follow, it�s too dangerous. That is final!� Luna, Hermione, Ginny and Ron�s faces fell at these words. They had been counting on Dumbledore.
�We must go! Harry needs our help. So, I think, does Neville Longbottom.� The others looked around, only noticing for the first time that Neville was not among them.
The order grabbed the small rock, which would take them back to the cave. It was a tight fit, but it seemed that all of their fingers could fit at some point on the rock. And with that, everyone except the four students, disappeared in a dull blue light.
They were all silent.
The order arrived in the cave, to see Harry and Voldemort duelling as fast as they could. The spells kept missing, which showed how good a duellers they were.
�Stupefy!� Harry yelled, as he got up from the ground. He had just dodged a very deadly looking purple spell, which had scraped his shoulder. Harry gritted his teeth as he watched Voldemort smirk.
Voldemort simply stepped out of the way, almost laughing at Harry�s feeble attempt, even though he was not doing to well himself.
He flicked his was in a very complicated way, showing his brilliance in magic. His lips moved slowly, as if hissing a spell.
The order members watched in fear at what he was going to do next. Even the semi conscious Tonks and Remus watched through half closed eyes.
The blood red colour spell burst out from his wand at many different angles, pushing everyone back into the walls. A large spurt of light continued out to reach Harry, who had managed to pull himself from the ground just in time.
�Protego!� And the spell was simply absorbed into a net of orange light, before disappearing into nothing. Harry sighed in relief and tried another spell.
The tickling charm, which Harry had no idea why he had used, hit the Dark Lord squarely in the chest. He bit his lip trying to hold back the temptations of a horrid laugh, before simply taking the spell off of him.
Harry grunted and tried again, this time it was the freezing charm. �Gelo Glacio!� He yelled. Everyone watched as the stream of light hit Voldemort yet again, who had just recovered from the last attack.
His whole body froze over. He was unable to move. Harry�s eyes widened at what he had done and he carefully starting to walk over to the now frozen dark wizard.
�Harry! Don�t move!� Remus yelled from above. Harry stopped to look up. Lupin was holding to the bars and trying his hardest to break them.
He felt a wave of guilt wash over him as he remembered what he was thinking before in Hogsmeade. He had not deserted him. He would have been there of it wasn't for Voldemort. Then Harry looked more closely. Tonks had her arms rapped around his middle, terrified of what may happen. It looked like they had just forgotten what had happened between them for this brief moment in time, and come together.
Harry smiled and looked back down again, but this time Voldemort wasn�t frozen.
�Crucio!� Voldemort shouted, hitting Harry in the side. Harry blinked slowly, trying to take in everything that had just happened.
Voldemort had been frozen.
Then he, Harry had looked up at Lupin�s words.
Now he wasn't frozen.
And Harry had been hit with the Cruciatus curse.
Why wasn't anything happening?
Voldemort was staring strangely at him, wand still pointed at the boy�s body. Though the spell had had no effect.
He lowered his wand and glared at him, before-
�Expelliarmus!� He yelled, and Harry felt his wand fly out of his hand. There was a small bit of a delayed reaction, before Harry was thrown against the wall.
�Arrrghhh...� Harry whispered as he felt the hard cave wall against his back. His eyes threatened to close as he fell to the ground in a heap. He was so tired. He just wanted it to end.
Then Harry noticed someone. Lying next to him was Neville�s body. It was still. Very still. There was no rising of his chest, and no flick in his fingers. Even his hair was unnaturally still.
Harry closed his eyes and remembered how brave Neville had been. He had performed a real Patronus. It had been a lion. A noble creature. Very brave. Harry felt so proud of him, and suddenly he felt he had more power.
Harry Potter lifted himself off the ground, no wand in hand, only the shear proudness of Neville Longbottom.
Abruptly there were pops everywhere, as death eaters started to appear. Harry could hear the members of the order start to through spells around him. However he did not focus on these. The only thing he focused on was the evil glare in his enemies red eyes.
Voldemort laughed and there were deep cackles coming from his chest. He watched Harry for a moment, before looking up at the cage.
�Harry, would you like to see something?� He asked over the noise that was going on around him.
Harry only stared. He didn't say a thing.
Voldemort looked up once again, this time pointing his wand at the cage.
�Harry, it�s either your life, of theirs. Your choice.� He said in an unnaturally calm voice.
Harry�s brows creased in worry, but still he did not answer.
The Dark Lord pointed his wand at Tonks, who no longer held onto Remus. Here eyes were half open, though she looked down on the wand in fear.
Voldemort didn't even say anything. A stream of different coloured light flew out of his wand and hit Tonks straight in the stomach.
�ARRRRRRRRRRRRRRGHHHHHHHHHHHH!� She screamed, clutching her bulging stomach. Everyone around them stopped to watch. Tears were steaming out of her eyes. He-Who-Must-Not-Be-Named only chuckled and concentrated on the spell.
A soft �Oh� was heard from Tonks's mouth, before she passed out completely, arms still holding her stomach.
No one moved.
�When was the baby due?�
No one said anything at stared at the Dark Lord in horror.
�YOU! YOU KILLED OUR BABY! CURSE YOU!� Remus yelled out of the change, squeezing the bars, rattling them together. His eyes were filled with tears, as he shouted.
�Yes, that's right.� The calm voice said. Voldemort turned to place a spell on Lupin, but Harry beat him to it.
While everyone had been watching Tonks and Remus, Harry had had enough time to grab his wand off the ground.
�Expelliarmus!� He yelled, catching Voldemort by surprise. The black wand of yew flew into his open hand. Harry looked at it carefully, then back at his enemy. This time there was no look of glee on the man�s fast. Only one of panic.
Harry took it into both hands hand squeezed his knuckles around it.
The wand�s pieces fell to the ground, a green stream of power falling out from it, and a single golden Phoenix feather.
Harry not only dropped Voldemort�s wand, but his own.
�This is going to be a fair fight!� Harry yelled over at him, not noticing that everyone in the cave was watching them, unmoving.
Meanwhile, Harry was trying to get his wandless magic to work. Trying his hardest to get any of his powers to work. But nothing was happening.
He scrunched his face and could feel sweat forming on his temples.
Voldemort was still starring in panic at his wand on the ground. His red eyes strangely human. Everyone watched and waited to see what the Dark Lord would do.
Suddenly Harry let out a huge scream.
Everyone turned to look at him before being thrown to the ground. The cave was shaking rapidly and rocks were flying from the roof. But were not falling onto the ground.
Everyone stared into the middle to see a huge hole appear. A crack in the rocks on the ground.
It had separated Harry from Voldemort, and both wands had rolled down to the centre of the earth.
Harry only watched his fall. Then he looked at Voldemort, wanting to do something, but instead he fell to his knees.
Dumbledore stepped forward. He had been there the whole time. He had watched everything happen. To of his best students had been in a fight, but neither had won. First he looked at Harry. His brows creased in worry. Then he looked at Tom, who still hadn�t moved. Tom was starring into the hole.
�Tom... You will never win. Harry is too powerful. Why not just give up?� He asked in his usual calm voice.
Voldemort hissed like a snake and stared venomously at Harry, returning to his old self.
�I will get you next time, Potter!� He yelled. He looked over at his death eaters. Some were on his side of the crack and some on the other. Most of them were captured or unconscious. He laughed. Watching them suffer. He didn't need them anymore. He was going to do it himself. He was powerful enough.
He clicked his long bony fingers, before he Disapparated in a shimmer of green light.
This was the last thing that Harry Potter saw, before he closed his eyes completely and fell to the ground.
A week Later -
Harry wandered into the room in which Mrs Longbottom, Neville�s Grandmother was mourning. Neville�s death had hit her hard. First her son and now Neville. They were both young, too young and now she had no one.
Harry watched her for a moment. She was holding onto Trevor, Neville�s pet toad for dear life. He then decided to make himself known.
�Mrs Longbottom...� He started, as she span around viciously, glaring at Harry with all her might. He wanted to continue, but she cut him off.
�Potter, listen to me. You stay away from Nymphadora! You hear me! I care a lot for my Great Niece. You are a danger to her, Potter, a danger to everyone.� Harry�s eyes widened suddenly in horror, but he understood. It was his fault Neville was dead, his fault that Tonks was in the room across the hall, not showing many signs of life.
�Potter, to tell you the truth, I think everything would be fine if you just left.� She said. Harry knew not to question this lady. She grew up in a time when children never spoke their minds, when children were never heard. If Harry was to talk now, her opinion of him would grow even more sour.
�Yes ma�am.� He said quietly as he left the room. He wandered to the small waiting room down the hallway and pulled out a small piece of parchment and a quill and ink. He had a feeling he would be needing these.
He scribbled down a small note to Tonks and folded it into an envelope.
Nymphadora Tonks was written in his neatest hand across the front.
He put his things away and entered Tonks�s room across the hallway, where Remus was sitting next to the bed. His eyes were red and sore and had bags under them. Harry quietly entered the room and set the letter on the bedside table, glancing quickly at Tonks still form. Her once beautifully kept long white hair was in mats and her face was a deadly pale colour.
He looked up at Remus who was watching him behind hurt eyes. He opened his mouth to say something, but was quite shocked at Remus�s behaviour.
�No, Harry. Just go, just leave.� As he said this, Remus was sure he saw something in Harry�s eyes that had not been there before. Yes there was regret, but there was something else.
Harry looked down at Tonks once more. He placed his hand on her pale forehead and his eyes glowed a faint white colour.
�Good-bye� He said in Remus�s head as he turned and walked out the room. At the same moment Harry�s footsteps died down, Tonks�s eyes sprung wide open. Remus jumped as he looked at her.
�Harry� She whispered as she looked to the door. She stole a glance at Remus, a worried glance, before falling back into unconsciousness.
Remus looked at her in wonder. Not knowing if Harry had said anything to her in her mind or not.
The last word Remus heard from Harry had been in his head. The significance of this was major. As Remus thought about it, he realised that what Harry had said could have been said out loud. Why had Harry chosen to use his powers? There had been a very flat tone to his good-bye, almost like it was forever.
At this Remus grabbed the letter from the bedside table and tore it open, not caring who is was addressed to.
�Harry!� He yelled as he sprinted down the hallway. But Harry had already gone.
As Harry left the room he rushed off down the hallway. He did not go and wait in the waiting room, he just kept running. Dark clouds littered the sky as Harry rushed out onto the street. He stole one last glance at the building before mounting Sirius�s old Motor bike.
He was glad when it had been given it, for he had felt free.
Harry was sure that during his last glance he looked up into the eyes of Remus Lupin, but this could have only been his mind playing tricks.
He kicked off the ground and tore down the road, into the distance, not daring to look back at the life he had just left.
The End.
Previous Chapter
|Write a Review
Harry Potter and the Army of Decendants: Chapter 50 - No Turning Back
Other Similar Stories
Unus Devoveo...
by Patronus ...


text:
Incremental project
Incremental is funded through the JISC Managing Research Data programme, with the aim to support researchers at the Universities of Cambridge and Glasgow. Through our scoping work (view Scoping Study Report (pdf)), we have found that many researchers are unclear about best practice in data management and unaware of where they could locate support and guidance. They wanted simple and engaging guidance and access to tailored support.
In response, we have:
- drawn together details of existing guidance and support on data management webpages
- provided training in data curation principles and techniques
- created audiovisual learning resources
As a key part of this effort, we are pleased to announce our new institution-specific websites, which are designed to provide support to staff and students who manage electronic research materials:
Cambridge Website: www.lib.cam.ac.uk/dataman/
Glasgow Website: www.gla.ac.uk/datamanagement/
Content produced by the Incremental project is released under Creative Commons licence BY-NC-SA. (Please note that we also link to external resources on these websites, which may be subject to other licences).
We'd love to hear if you reuse our work or have comments on our project!


text:
Millions of medical marijuana patients hit America's roads this upcoming week for another hectic holiday travel season. Experts say standard common sense applies with regard to the still-federally illegal marijuana. Medical or not, don't get caught, or it could be a hassle.
Federal statistics show 91 percent of long-distance holiday travel is by car with perhaps 43.4 million Americans traveling 50 miles or more from home during the Thanksgiving holiday weekend.
"Under California law medical cannabis patients are only allowed to transport what's reasonably related to your medical need considering distance, method and timing of transportation," said Omar Figueroa, a cannabis-specialized attorney in Northern California. That means a personal amount, not three pounds, Figueroa notes.
"And the laws don't travel with you," he said. "Many times people live in the freedom bubble, they see freedom all around them, then they're traveling to places of less freedom and they make a mistake and drop their their guard."
For example, users of medical cannabis from California who drive sober into Nevada, Utah or Arizona are technically DUI when they cross state lines.
In Nevada, a person is guilty of DUI if he or she is found to be driving with trace amounts of marijuana byproducts in their system. These traces can linger in the body for weeks after use.
"This is a per se offense – impairment is not an element of the offense. The mere presence of cannabis metabolites above the threshold constitutes a crime," NORML notes.
A first offense misdemeanor DUI in Nevada means prison of not less than 2 days or 48 hours of community service and a minimum $400 fine.
In Arizona, it is unlawful for a person to drive a vehicle while there is any drug or its metabolite in the person's body, which is a loony as it sounds. "Actual impairment is not an element of this offense. Cannabis metabolites can be detected in a person's body up to one month after use, thus it is possible to be convicted of this type of DUI weeks after a person last ingested cannabis," NORML writes.
Ditto for Utah.
Figueroa advises keeping your bag sealed and locked up in the trunk, and don't break any laws.
"Only break one law at a time. If you're speeding don't smoke weed in your car," he said.
Make sure your headlights and taillights work, and your registration is current.
Or as Sacramento comedian and marijuana advice columnist Ngaio Bealum puts it "don't be a dumbass."
And be especially careful around the international border, Bealum notes. Homeland Security and Customs works up to 100 miles from the border and regularly search random vehicles with drug dogs at checkpoints. The feds don't care about a small amount of pot "unless you're being a dick or they want to be a real jerk," Bealum said.FLYING WITH IT
As far as flying with medical cannabis, the big news in 2013 is that the Transportation Security Administration very publicly relaxed its policy with regard to marijuana. The TSA now states that they don't look for drugs, but if they find any they'll turn you over to local cops.
"It seems like 9-11 has been a boon to pot smokers," Dale Gieringer, head of California NORML. "I haven't heard of people getting stopped in a quite a while."
"They're not looking for small amounts of weed," said Bealum, a frequent traveler. "They're looking for 'a bomb' not 'the bomb'."
Bealum recently got stopped walking through a Midwestern airport security checkpoint with some medical cannabis in his shirt pocket. The TSA deemed it not a threat and waved him on.
Figueroa notes that TSA's general pot policy is to defer to local authorities. "So, for example in Oakland they respect medical marijuana law," he said.
Conversely, Gieringer's heard reports that Burbank and San Diego airports have been less respectful. Fliers can call ahead and ask for the airport's police department policy on medical cannabis.
If you're going to fly with it, Figueroa recommends sealing it up tight and stashing it in some checked luggage. And don't declare it, Figueroa said.
If you get popped, "don't run your mouth," Figueroa said. "If you're taking it to someone who is sick in a non-medical marijuana state, don't say that, because you're going to jail."
Gieringer said patients appear to be OK just carrying it on their person or in their checked luggage.
But again — not traveling with pot is probably the least stressful option.
Think of it as a tolerance break, or a chance to buy locally at your destination.
"It's not like you can't find weed everywhere in the U.S., even in Nebraska," Bealum said.
How do you roll out on the holidays? Start the conversation at StT.org


text:
Florida Sinkholes
Sinkhole:02-034 (Citrus County, 1994)
Sinkhole Reference Number: 02-034
Verified Sinkhole:
Date: Sept. 22, 1994
USGS Quadrangle Name: Chassahowitzka
Size Dimensions: Estimated
Shape of Sinkhole: Circular
Length: 2 ft
Width: 2 ft
Depth: 2 ft
Slope of Sides: 45
Water Visible: No
Water Below Land Surface: -
Limestone Visible: No
Cave Visible: No
Subsidence Rate: Unknown
Triggering Mechanisms: Ground Loading
Pre-collapse indicators: 0
Property Damage: No
Sinkhole Repaired: No
Repair Planned: Yes
Landuse Codes: Suburban (Low Density Residential)
Soil Type: Fine Sand
Comments: END. . . . . . .
Source: Florida Department of Environmental Protection