Created
June 7, 2011 17:04
-
-
Save toddtreece/1012658 to your computer and use it in GitHub Desktop.
SparkFun KML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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