Skip to content

Instantly share code, notes, and snippets.

@toddtreece
Created June 7, 2011 17:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toddtreece/1012658 to your computer and use it in GitHub Desktop.
Save toddtreece/1012658 to your computer and use it in GitHub Desktop.
SparkFun KML
<?php
/**
* Generates KML for use with SparkVisualize
*
* @author Todd Treece
*/
class SparkKml {
const SFE_LAT = '40.0648970';
const SFE_LNG = '-105.2099410';
private $dom;
private $kml;
private $document;
public function __construct($name='') {
$this->dom = new DOMDocument('1.0', 'UTF-8');
$this->kml = $this->dom->createElement('kml');
$this->kml->setAttribute('xmlns','http://earth.google.com/kml/2.1');
$this->document = $this->dom->createElement('Document');
$this->document->appendChild($this->dom->createElement('name',htmlentities($name)));
$shippingcolor = $this->createLineStyle('sfe_shipment',2,1,'FF2835F0','7DFFFFFF');
$ordercolor = $this->createLineStyle('sfe_order',2,1,'FF4EF028','7DFFFFFF');
$bluecircle = $this->createCircleStyle('sfe_order_circle',5,'7dff0000');
$redcircle = $this->createCircleStyle('sfe_shipment_circle',5,'7d0000ff');
$this->document->appendChild($shippingcolor);
$this->document->appendChild($ordercolor);
$this->document->appendChild($bluecircle);
$this->document->appendChild($redcircle);
$this->lookAt(self::SFE_LAT,self::SFE_LNG);
}
public function createLine($lat,$lng,$styleid,$name='',$description='') {
$placemark = $this->dom->createElement('Placemark');
$placemark->appendChild($this->dom->createElement('name',htmlentities($name)));
$placemark->appendChild($this->dom->createElement('description',htmlentities(preg_replace('/[^(\x20-\x7F)]*/','',$description))));
$placemark->appendChild($this->dom->createElement('styleUrl',$styleid));
$line = $this->dom->createElement('LineString');
$line->appendChild($this->dom->createElement('tessellate', '1'));
$line->appendChild($this->dom->createElement('extrude', '0'));
$line->appendChild($this->dom->createElement('altitudeMode', 'clampToGround'));
$destination = $lng . ',' . $lat . ',' . '0';
$sfe = self::SFE_LNG . ',' . self::SFE_LAT . ',' . '0';
$midarray = $this->getMidpoint(self::SFE_LAT,self::SFE_LNG,$lat,$lng);
$midalt = $this->getMidpointAltitude(self::SFE_LAT,self::SFE_LNG,$midarray['lat'],$midarray['lng']);
$midpoint = $midarray['lng'] . ',' . $midarray['lat'] . ',' . $midalt;
$line->appendChild($this->dom->createElement('coordinates', $destination /*. ' ' . $midpoint */ . ' ' . $sfe));
$placemark->appendChild($line);
$this->document->appendChild($placemark);
}
public function createCircle($lat, $lng, $radius, $style) {
$placemark = $this->dom->createElement('Placemark');
$placemark->appendChild($this->dom->createElement('styleUrl',$style));
$polygon = $this->dom->createElement('Polygon');
$boundry = $this->dom->createElement('outerBoundaryIs');
$ring = $this->dom->createElement('LinearRing');
$ring->appendChild($this->dom->createElement('tessellate', '1'));
$radius = $radius/500;
$steps = 40;
$angle = 0;
$coordinates = array();
for ($i = 0; $i < $steps; $i++) {
$coordinates[] = ($lng + $radius * cos($angle)) . ',' .
($lat + $radius * sin($angle)) . ',' .
'0';
$angle += 6.28 / $steps;
}
$coordinates[] = $coordinates[0];
$ring->appendChild($this->dom->createElement('coordinates',implode(' ',$coordinates)));
$boundry->appendChild($ring);
$polygon->appendChild($boundry);
$placemark->appendChild($polygon);
$this->document->appendChild($placemark);
}
public function save() {
$this->kml->appendChild($this->document);
$this->dom->appendChild($this->kml);
$this->dom->formatOutput = true;
return($this->dom->saveXML());
}
private function createCircleStyle($id,$width,$color) {
$style = $this->dom->createElement('Style');
$style->setAttribute('id',$id);
$linestyle = $this->dom->createElement('LineStyle');
$linestyle->appendChild($this->dom->createElement('width', $width));
$style->appendChild($linestyle);
$polystyle = $this->dom->createElement('PolyStyle');
$polystyle->appendChild($this->dom->createElement('color', $color));
$style->appendChild($polystyle);
return $style;
}
private function createLineStyle($id,$width,$outerwidth,$color,$outercolor) {
$style = $this->dom->createElement('Style');
$style->setAttribute('id',$id);
$linestyle = $this->dom->createElement('LineStyle');
$linestyle->appendChild($this->dom->createElement('color', $color));
$linestyle->appendChild($this->dom->createElement('width', $width));
$linestyle->appendChild($this->dom->createElement('gx:physicalWidth', floatval($width)));
$linestyle->appendChild($this->dom->createElement('gx:outerColor', $outercolor));
$linestyle->appendChild($this->dom->createElement('gx:outerWidth', floatval($outerwidth)));
$style->appendChild($linestyle);
return $style;
}
private function getMidpointAltitude($lat,$lng,$lat2,$lng2) {
$radius = 6371000; // radius of earth in meters
//trig functions take radians
$lat = deg2rad($lat);
$lng = deg2rad($lng);
$lat2 = deg2rad($lat2);
$lng2 = deg2rad($lng2);
$diffLat = $lat2-$lat;
$diffLng = $lng2-$lng;
// http://en.wikipedia.org/wiki/Haversine_formula
$a = sin($diffLat/2) * sin($diffLat/2) +
cos($lat) * cos($lat2) *
sin($diffLng/2) * sin($diffLng/2);
$c = 2 * atan2(sqrt($a), sqrt(1-$a));
$distance = $radius * $c;
return $distance;
}
/**
* Ported from http://www.movable-type.co.uk/scripts/latlong.html#midpoint
* @return array
*/
private function getMidpoint($lat,$lng,$lat2,$lng2) {
//trig functions take radians
$lat = deg2rad($lat);
$lng = deg2rad($lng);
$lat2 = deg2rad($lat2);
$lng2 = deg2rad($lng2);
$diffLng = $lng2 - $lng;
$x = cos($lat2) * cos($diffLng);
$y = cos($lat2) * sin($diffLng);
$midLat = atan2(sin($lat)+sin($lat2), sqrt((cos($lat)+$x)*(cos($lat)+$x) + $y * $y));
$midLng = $lng + atan2($y, cos($lat) + $x);
$return = array();
$return['lat'] = rad2deg($midLat);
$return['lng'] = rad2deg($midLng);
return $return;
}
private function lookAt($lat,$lng,$alt='10000000',$range='500',$tilt='0',$heading='0') {
$look = $this->dom->createElement('LookAt');
$look->appendChild($this->dom->createElement('longitude',$lng));
$look->appendChild($this->dom->createElement('latitude',$lat));
$look->appendChild($this->dom->createElement('altitude',$alt));
$look->appendChild($this->dom->createElement('range',$range));
$look->appendChild($this->dom->createElement('tilt',$tilt));
$look->appendChild($this->dom->createElement('heading',$heading));
$look->appendChild($this->dom->createElement('altitudeMode','relativeToGround'));
$this->document->appendChild($look);
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment