Skip to content

Instantly share code, notes, and snippets.

@milkbread
Last active December 18, 2015 12:19
Show Gist options
  • Save milkbread/5781958 to your computer and use it in GitHub Desktop.
Save milkbread/5781958 to your computer and use it in GitHub Desktop.
HTML: Clipping 1st running demo

Aggregation Demo

this is a first demo on my aggregation algorithm

What happens:
  • you can click a feature
  • automatically, the best fitting neighbor is searched
  • and the clicked feature gets aggregated to the found one
Currently under construction:
  • neighbor detection
  • aggregtion
<!DOCTYPE html>
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.js"></script>
<!--<script src="https://gist.github.com/milkbread/5713629/raw/RKMapping_0.4.js"></script>-->
<script src="http://bl.ocks.org/milkbread/raw/5779939/RKMapping_0.4.js"></script>
<style>
@import url(http://bl.ocks.org/milkbread/raw/5713683/myStyles.css);
@import url(http://cdn.leafletjs.com/leaflet-0.5/leaflet.css);
#map {
width: 960px;
height: 500px;
}
#polys:hover{
fill:rgba(200,0,0,0.8);
}
#polys{
stroke-width:1px;
stroke:rgba(255,255,255,1);
}
#polys2{
stroke-width:3px;
stroke:rgba(255,0,0,1);
fill:rgba(0,255,0,0.5)
}
.overlay_poly{
fill:rgba(100,100,100,0.3);
}
.overlay_multipoly{
fill:rgba(0,0,0,0.7);
}
.clipped_poly{
fill:rgba(255,0,0,0.7);
}
#delaunay{
fill:none;
stroke:rgba(0,0,255,1);
stroke-width:1px;
}
#points{
fill:#000;;
}
</style>
</head>
<body>
<div id=map></div>
<script>
var jsonFile = "milkbread/raw/5754788/vg250_clipped_mini_topo.json"
var prefix = "http://bl.ocks.org/"
if(location.hostname=='localhost')prefix=""
var jsonURL=prefix+jsonFile
var map = L.map('map').setView([49.36,7.29], 10);//.setView([49.46,7.49], 12);//.setView([51.25, 11], 6);
var stamen = L.tileLayer('http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png', {attribution: 'Add some attributes here!'}).addTo(map);
var baseLayers = {"stamen": stamen};
L.control.layers(baseLayers).addTo(map);
//var overLayer2 = new mapOverlay(map);
var overLayer = new mapOverlay(map);
var infoContainer = d3.select("body").append("info").text("This will show you some information!")
d3.select("body").append("br")
var mouseInfo = d3.select("body").append("info").text("")
function myFunction(){
console.log("hallo")
}
var maximum = 0;
d3.json(jsonURL, function(error, topology) {
var pure_states = topology.objects.vg250_gem_clipped3;
var removedFeatureStorage = new remFeatureStorage();
//create the feature objects ... containing all necessary objects and functions for processing
var featureStorage = new featureObjStorage();
pure_states.geometries.forEach(function(d){ featureStorage.addFeatObj(d) })
var featuresObjects = featureStorage.featureObjects;
//console.log(featuresObjects);
//console.log(featuresObjectsIndizes);
//get all arc-geometries of the selected objects 'pure_states'...can be simplified directly
var arcCollection = getArcs_V2(topology, featuresObjects);
polygons = getGeometries_V2(featuresObjects, arcCollection)
//build a GeometryCollection, for the visualisation of features
var polyCollection = {type: 'GeometryCollection', geometries:polygons};
overLayer.addGeometries(polygons,"path");
map.on("viewreset", reset);//.on("move",function(){console.log(map.getCenter(),map.getZoom())})
doStyling();
reset();
function testing(data){
//This is a test on detecting which part of a MultiPolygon has to be edited ...
//!!!HAS TO BE REPLACED!!! against a check who fits to the used criterium ... currently the criterium is the click!
console.log(data, d3.geo.bounds(data),d3.mouse(this));
var mouse_coords = map.layerPointToLatLng(d3.mouse(this))
console.log(mouse_coords, mouse_coords.lat)
var fixed_multiPolyIndex = -1; //this variable is only defined for MultiPolygons and tells me which one of the 'multi'-possibilities the selected on is...by its index
if(data.type=='MultiPolygon')data.coordinates.forEach(function(d,i){
var this_bounds = d3.geo.bounds({type: 'Polygon', coordinates: d})
//console.log(this_bounds)
if((mouse_coords.lng>this_bounds[0][0] && mouse_coords.lng<this_bounds[1][0]) && (mouse_coords.lat>this_bounds[0][1] && mouse_coords.lat<this_bounds[1][1]))fixed_multiPolyIndex = i;
})
//++++++++++++++
overLayer.removeAll();
doAggregation(data.id, fixed_multiPolyIndex);
polygons = getGeometries_V2(featuresObjects, arcCollection)
overLayer.addGeometries(polygons,"path");
overLayer.showAll();
doStyling();
}
function doAggregation(id, fixed_multiPolyIndex_){
var featuresObjectsIndizes = featureStorage.getIndizes(); //stores the IDs of all features ... to search the easier
var test2 = featuresObjectsIndizes.indexOf(id);
var featureObject = featuresObjects[test2];
var polygons2 = [], removed_features = [];
console.log("###Begin the aggregation###")
console.log("This the id the of the analysed feature: ",featureObject.id)
console.log("... it is a: ",featureObject.type)
var single_geoms = featureObject.getSingleGeometries();
console.log("These are my single geometries (without holes): ",single_geoms)
var arcs = featureObject.getArcsPure();
var neighbors = featureObject.getNeighbors(arcCollection, fixed_multiPolyIndex_);
console.log("These are my neighbors: ",neighbors)
//~~~~Different solutions are possible
var sorted_neighbors = sortArcs(neighbors, arcCollection)
var was_removed = false, stop=false; i=0;
while(stop==false){
var longest_neigh = sorted_neighbors[i];
console.log("This is the longest neighbor: ",longest_neigh, " ...as it is the first in an DESC-sorted array")
var removedIndex = removedFeatureStorage.getIndizes().indexOf(longest_neigh.id)
if(removedIndex != -1)was_removed=true
else { stop=true; was_removed=false};
console.log("Was this feature already removed? ",was_removed, removedIndex)
i++;
//stop the loop when there is no more neighbor
if(sorted_neighbors[i]==undefined)stop=true;
}
//~~~~~~~~~~~~~~~~
if(was_removed==false){
console.log("...that means we want to aggregate this feature: ",longest_neigh.id," (add to candidate)", " with this feature: ",featureObject.id, "(origin) ")
//now we have to find the corresponding feature
var addToCandidateIndex = featuresObjectsIndizes.indexOf(longest_neigh.id);
//-1 means ... nothing found ... that means ... it was already removed ... so we have to search in the removed features array, to find out where it was aggregated to
if(addToCandidateIndex==-1){
var cacheIndex = removedFeatureStorage.getIndizes().indexOf(longest_neigh.id); //the index in the removed features array
var cacheOrigin = removedFeatureStorage.removedFeatures[cacheIndex]; //the removed feature object ... it tells us where it was aggregated to by *.id_new
addToCandidateIndex = featuresObjectsIndizes.indexOf(cacheOrigin.id_new); //use this id to get the new aggregate that contains the searched feature
}
var addToCandidate = featuresObjects[addToCandidateIndex];
console.log("...and with help of the index: "+addToCandidateIndex+" ...I can find the add to candidate: ",addToCandidate)
//if there is more than neighboring arc for the addToCandidate
var additionalNeighborArcs = checkForRedundantFeatures(sorted_neighbors, longest_neigh)
var removedArc = addToCandidate.aggregateFeature(featureObject, longest_neigh, additionalNeighborArcs);
console.log("This is the removed arc: ",removedArc)
var originIndex = featuresObjectsIndizes.indexOf(featureObject.id)
console.log("Did I find the origin to remove it: ",originIndex)
console.log("Das array vorm Entfernen: ",featuresObjects.length)
//remove the -origin- feature from the storage
featureStorage.removeFeatObj(featureObject, removedFeatureStorage, addToCandidate, fixed_multiPolyIndex_)
console.log(" ... und danach: ",featuresObjects.length)
/* NOT necessary to remove the redundant arc
//remove the redundant (removed) arc from the arcCollection
console.log("This arc has to be removed: ",arcCollection[removedArc])
//delete arcCollection[removedArc];
console.log("This arc has to be removed: ",arcCollection[removedArc]) */
console.log("###Done the aggregation###")
//build the geometries using geometries in arcCollection
var test_geom = [];
}else console.log("!!!Cannot find any neighbor that was not already removed...fix this bug...pleas!!!")
}
function doStyling(){
overLayer.features.attr("class",function(d){if(d.clipped==true) return "clipped_poly"; else {if(d.type=="Polygon")return "overlay_poly"; else if(d.type=="MultiPolygon") return "overlay_multipoly"; }})
.attr("id","polys")
.on("mouseover",showInfo)
.on("mouseup",testing);
}
function reset(){
var start_time = Date.now();
overLayer.resetView(d3.geo.bounds(polyCollection));
overLayer.showAll();
console.log("initial load took: "+((Date.now() - start_time)/1000).toFixed(2)+"s")
}
function showInfo(value){
mouseInfo.text("Center: "+map.getCenter()+" Zoom: "+map.getZoom())
infoContainer.text("You hovered over: "+value.properties.GEN +' - Type: '+value.type +' - ID: '+value.id )
//console.log(' - neighbors: ', polygons_indexed[value.id].neighbors)
}
function zoomToObject(d){
var local_bounds = d3.geo.bounds(d),
center = new L.LatLng(local_bounds[0][1]+((local_bounds[1][1]-local_bounds[0][1])/2),local_bounds[0][0]+((local_bounds[1][0]-local_bounds[0][0])/2)),
southWest = new L.LatLng(local_bounds[0][1], local_bounds[0][0]),
northEast = new L.LatLng(local_bounds[1][1], local_bounds[1][0]);
var local_bounds = new L.LatLngBounds(southWest, northEast);
map.setView( center, map.getBoundsZoom( local_bounds));
}
})
function reShow(maxVal){
maximum = maxVal;
overLayer.showAllFiltered(maxVal);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment