Created
November 22, 2013 06:47
-
-
Save mashbridge/7595864 to your computer and use it in GitHub Desktop.
Create cubic polygons in 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
// This program accepts a center point (lat, lng, alt) and a distance (in m) | |
// and generates a cube of side distance around that point. | |
// e.g. ./cubegen 37.0 -122.0 1000 200 | |
#include <iostream> | |
#include <string> | |
#include <vector> | |
#include "kml/base/math_util.h" | |
#include "kml/dom.h" | |
#include "kml/convenience/convenience.h" | |
using std::cerr; | |
using std::cout; | |
using std::endl; | |
using kmldom::KmlFactory; | |
using kmlbase::Vec3; | |
typedef std::vector<Vec3> VertexArray; | |
static int altitudeMode = kmldom::ALTITUDEMODE_ABSOLUTE; | |
kmldom::PolygonPtr CreatePolygon(KmlFactory* factory, | |
const VertexArray& vertices) { | |
VertexArray::const_iterator it; | |
kmldom::CoordinatesPtr c = factory->CreateCoordinates(); | |
for (it = vertices.begin(); it != vertices.end(); it++) { | |
c->add_latlngalt(it->get_latitude(), it->get_longitude(), | |
it->get_altitude()); | |
} | |
// A LinearRing is a closed loop. | |
c->add_latlngalt(vertices.at(0).get_latitude(), | |
vertices.at(0).get_longitude(), | |
vertices.at(0).get_altitude()); | |
kmldom::LinearRingPtr lr = factory->CreateLinearRing(); | |
lr->set_coordinates(c); | |
kmldom::OuterBoundaryIsPtr ob = factory->CreateOuterBoundaryIs(); | |
ob->set_linearring(lr); | |
kmldom::PolygonPtr polygon = factory->CreatePolygon(); | |
polygon->set_outerboundaryis(ob); | |
polygon->set_altitudemode(altitudeMode); | |
return polygon; | |
} | |
kmldom::PlacemarkPtr CreateCube(KmlFactory* factory, double center_lat, | |
double center_lon, double center_alt, double distance) { | |
// Project the walls from the center point. | |
Vec3 north = kmlbase::LatLngOnRadialFromPoint(center_lat, center_lon, | |
distance, 0.0); | |
Vec3 east = kmlbase::LatLngOnRadialFromPoint(center_lat, center_lon, | |
distance, 90.0); | |
Vec3 south = kmlbase::LatLngOnRadialFromPoint(center_lat, center_lon, | |
distance, 180.0); | |
Vec3 west = kmlbase::LatLngOnRadialFromPoint(center_lat, center_lon, | |
distance, 270.0); | |
// Project the corners from the walls. | |
Vec3 ne = Vec3(east.get_longitude(), north.get_latitude()); | |
Vec3 se = Vec3(east.get_longitude(), south.get_latitude()); | |
Vec3 sw = Vec3(west.get_longitude(), south.get_latitude()); | |
Vec3 nw = Vec3(west.get_longitude(), north.get_latitude()); | |
kmldom::MultiGeometryPtr mg = factory->CreateMultiGeometry(); | |
double max_alt = center_alt + distance / 2; | |
double min_alt = center_alt - distance / 2; | |
// Draw the floor. | |
// CW winding order, normal points into earth. | |
VertexArray floor; | |
floor.push_back(Vec3(ne, min_alt)); | |
floor.push_back(Vec3(se, min_alt)); | |
floor.push_back(Vec3(sw, min_alt)); | |
floor.push_back(Vec3(nw, min_alt)); | |
mg->add_geometry(CreatePolygon(factory, floor)); | |
// Draw the ceiling. | |
// CCW winding order, normal points to sky. | |
VertexArray ceiling; | |
ceiling.push_back(Vec3(ne, max_alt)); | |
ceiling.push_back(Vec3(nw, max_alt)); | |
ceiling.push_back(Vec3(sw, max_alt)); | |
ceiling.push_back(Vec3(se, max_alt)); | |
mg->add_geometry(CreatePolygon(factory, ceiling)); | |
// North wall. | |
VertexArray north_wall; | |
north_wall.push_back(Vec3(ne, max_alt)); | |
north_wall.push_back(Vec3(ne, min_alt)); | |
north_wall.push_back(Vec3(nw, min_alt)); | |
north_wall.push_back(Vec3(nw, max_alt)); | |
mg->add_geometry(CreatePolygon(factory, north_wall)); | |
// East wall. | |
VertexArray east_wall; | |
east_wall.push_back(Vec3(se, max_alt)); | |
east_wall.push_back(Vec3(se, min_alt)); | |
east_wall.push_back(Vec3(ne, min_alt)); | |
east_wall.push_back(Vec3(ne, max_alt)); | |
mg->add_geometry(CreatePolygon(factory, east_wall)); | |
// South wall. | |
VertexArray south_wall; | |
south_wall.push_back(Vec3(sw, max_alt)); | |
south_wall.push_back(Vec3(sw, min_alt)); | |
south_wall.push_back(Vec3(se, min_alt)); | |
south_wall.push_back(Vec3(se, max_alt)); | |
mg->add_geometry(CreatePolygon(factory, south_wall)); | |
// West wall. | |
VertexArray west_wall; | |
west_wall.push_back(Vec3(nw, max_alt)); | |
west_wall.push_back(Vec3(nw, min_alt)); | |
west_wall.push_back(Vec3(sw, min_alt)); | |
west_wall.push_back(Vec3(sw, max_alt)); | |
mg->add_geometry(CreatePolygon(factory, west_wall)); | |
kmldom::PlacemarkPtr p = factory->CreatePlacemark(); | |
p->set_geometry(mg); | |
p->set_name("cube"); | |
return p; | |
} | |
int main(int argc, char** argv) { | |
if (argc != 5) { | |
cerr << "usage: " << argv[0] << " lat lng alt distance" << endl; | |
return 1; | |
} | |
double center_lat = strtod(argv[1], NULL); | |
double center_lng = strtod(argv[2], NULL); | |
double center_alt = strtod(argv[3], NULL); | |
double distance = strtod(argv[4], NULL); | |
KmlFactory* factory = KmlFactory::GetFactory(); | |
kmldom::PlacemarkPtr cube = CreateCube(factory, center_lat, center_lng, | |
center_alt, distance); | |
kmldom::DocumentPtr document = factory->CreateDocument(); | |
document->add_feature(cube); | |
kmldom::KmlPtr kml = factory->CreateKml(); | |
kml->set_feature(document); | |
cout << kmldom::SerializePretty(kml); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment