Skip to content

Instantly share code, notes, and snippets.

@mashbridge
Created November 22, 2013 06:47
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 mashbridge/7595864 to your computer and use it in GitHub Desktop.
Save mashbridge/7595864 to your computer and use it in GitHub Desktop.
Create cubic polygons in KML
// 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