mirror of
https://github.com/NASAWorldWind/WebWorldWind.git
synced 2026-01-18 15:12:57 +00:00
215 lines
8.7 KiB
JavaScript
215 lines
8.7 KiB
JavaScript
/**
|
|
* Created by Matthew on 8/13/2015.
|
|
*/
|
|
/*
|
|
* This modules calls the polygon api, calls the building info api.
|
|
*
|
|
*
|
|
*/
|
|
define(['OSMBuildingDataRetriever',
|
|
'BuildingFactory',
|
|
'lodash',
|
|
'OpenStreetMapConfig'],
|
|
function (OSMBuildingDataRetriever,
|
|
BuildingFactory,
|
|
_,
|
|
OpenStreetMapConfig) {
|
|
|
|
/*
|
|
Given a WorldWind Location or WorldWind Position, uses the maximum bounding
|
|
box distances from the config object to define a bounding box for usage in
|
|
the OpenStreetMap API and the RTree.
|
|
@param center : the object containing the longitude and latitude points of the bounding rect's
|
|
center point
|
|
@return : returns an array, [top, left, bottom, right], that represents the bounding rectangle
|
|
*/
|
|
function getBoundingRectLocs (center, grid) {
|
|
var jQueryDoc = $(window.document),
|
|
jQH = jQueryDoc.height(),
|
|
jQW = jQueryDoc.width(),
|
|
R = jQH/jQW,
|
|
size = (grid ||.002);
|
|
|
|
center.latitude = Math.round(center.latitude/(2*size))*(2*size);
|
|
center.longitude = Math.round(center.longitude/(2*size/R))*(2*size/R);
|
|
|
|
return [
|
|
center.latitude + size,
|
|
center.longitude - size/R,
|
|
center.latitude - size,
|
|
center.longitude + size/R
|
|
];
|
|
|
|
}
|
|
|
|
/*
|
|
* Arranges the ordering of a bounding box array in an appropriate manner to be used with rbush
|
|
*
|
|
* @param bbox: any bounding box array
|
|
*
|
|
* @return: Returns bounding box in the form [minlat, minlong, maxlat, maxlon]
|
|
*/
|
|
function bboxToNode (bbox) {
|
|
return [
|
|
Math.min(bbox[0],bbox[2]),
|
|
Math.min(bbox[1],bbox[3]),
|
|
Math.max(bbox[0],bbox[2]),
|
|
Math.max(bbox[1],bbox[3])
|
|
]
|
|
}
|
|
|
|
var BuildingPolygonHandler = function ( layer ) {
|
|
var self = this;
|
|
|
|
self._OSMBuildingData = new OSMBuildingDataRetriever();
|
|
self._buildingFactory = new BuildingFactory();
|
|
self._config = new OpenStreetMapConfig();
|
|
self._tempBuildingIDTracker = [];
|
|
self._layer = layer;
|
|
self._boxesOwned = {};
|
|
|
|
/*
|
|
* Manages building and bounding box calls. Acts as an access point by the layer. The layer calls this
|
|
* function with draw context as an arg.
|
|
*
|
|
* @param drawContext: Drawcontext of layer
|
|
*/
|
|
self.buildingHandler = function (drawContext) {
|
|
|
|
//console.log(drawContext)
|
|
var callCompleteCallback = function () {self.isInCall = false;};
|
|
var eyeAltitude = drawContext.eyePosition.altitude;
|
|
var box = getBoundingRectLocs(
|
|
{
|
|
latitude: drawContext.eyePosition.latitude,
|
|
longitude: drawContext.eyePosition.longitude
|
|
}
|
|
|
|
);
|
|
|
|
if (!self.isInCall && eyeAltitude <= self._config._maxBuildingDrawHeight) {
|
|
self.isInCall = true;
|
|
self.getBuildingArrayAndType(
|
|
box,
|
|
self.buildingRenderableHandler,
|
|
callCompleteCallback
|
|
);
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
/*
|
|
* Behaves as callback function for the api caller to add renderables to the layer.
|
|
*
|
|
* @param building: a renderable building abstraction from the building module.
|
|
*/
|
|
self.buildingRenderableHandler = function (building) {
|
|
if (building) {
|
|
self._layer.addRenderable(building, function(renderable){return renderable.bbox})
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
/*
|
|
* If a bounding box has not been called for yet, it calls the api with that bounding box then calls the second
|
|
* api for the building details. Bounding boxes are stored in a key object for checking if a box has been
|
|
* called for already. Upon return from the last of the buildings, the call is opened up again for another
|
|
* call.
|
|
*
|
|
* @param box: bounding box in the form given by the getboudingrecslocs function.
|
|
* @param buildingRetreivedCallback: Function to call when a single building date has been returned. This is
|
|
* called with the building as an argument.
|
|
* @param CompletionCallback: Callback function to call when the last few of the buildings are retrieved or if
|
|
* the call has already been made.
|
|
*/
|
|
BuildingPolygonHandler.prototype.getBuildingArrayAndType = function (
|
|
box,
|
|
buildingRetreivedCallback,
|
|
CompletionCallback) {
|
|
var self = this;
|
|
//console.log('called')
|
|
var box = [box[0], box[3], box[2], box[1]];
|
|
//console.log(box)
|
|
var boxKey = (box.map(function(entry){return entry.toFixed(5)})).join(',');
|
|
//console.log(boxKey)
|
|
if (!self._boxesOwned[boxKey]) {
|
|
self._boxesOwned[boxKey] = true;
|
|
self._OSMBuildingData.requestOSMBuildingData(box, function (buildingIdArray) {
|
|
var numberOfBuildingsFullyRetreived = 0;
|
|
buildingIdArray.forEach(function (buildingData) {
|
|
var building = self.buildingFromDatum(buildingData);
|
|
if (self._tempBuildingIDTracker.indexOf(building.id) === -1) {
|
|
self._tempBuildingIDTracker.push(building.id);
|
|
self._OSMBuildingData.requestBuildingInfoById(building.id, function (data) {
|
|
var features = data['features'];
|
|
if (features) {
|
|
var first = features[0];
|
|
}
|
|
if (first) {
|
|
var properties = first['properties'];
|
|
}
|
|
if (properties) {
|
|
var tags = properties['tags'];
|
|
}
|
|
if (tags) {
|
|
var buildingType = tags['building'];
|
|
}
|
|
if (buildingType) {
|
|
building.buildingType = buildingType;
|
|
}
|
|
|
|
if (building.buildingType) {
|
|
building.bbox = bboxToNode(box);
|
|
buildingRetreivedCallback(building)
|
|
}
|
|
numberOfBuildingsFullyRetreived++;
|
|
//console.log(numberOfBuildingsFullyRetreived, 'of', buildingIdArray.length)
|
|
if (numberOfBuildingsFullyRetreived >= buildingIdArray.length - 5) {
|
|
CompletionCallback()
|
|
}
|
|
|
|
});
|
|
} else {
|
|
numberOfBuildingsFullyRetreived++;
|
|
//console.log(numberOfBuildingsFullyRetreived, 'of', buildingIdArray.length)
|
|
if (numberOfBuildingsFullyRetreived >= buildingIdArray.length - 5) {
|
|
CompletionCallback()
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
})
|
|
} else {
|
|
//console.log('This is an old box');
|
|
CompletionCallback()
|
|
}
|
|
};
|
|
|
|
/*
|
|
* Puts building data from the api into a form that we can work with.
|
|
*
|
|
* @param buildingData: Building data as returned by the api
|
|
*
|
|
* @return: building renderable abstraction as given by the building module.
|
|
*/
|
|
BuildingPolygonHandler.prototype.buildingFromDatum = function(buildingData) {
|
|
var self = this;
|
|
var id = buildingData['id'];
|
|
var geometry = buildingData['geometry'];
|
|
var coordinates = geometry['coordinates'];
|
|
var points = coordinates[0];
|
|
var polygon = _.map(points, function(point) {
|
|
return new WorldWind.Position(point[1], point[0], 100);
|
|
});
|
|
|
|
return self._buildingFactory.createBuilding(id, polygon, undefined);
|
|
};
|
|
|
|
return BuildingPolygonHandler
|
|
}
|
|
); |