Skip to content

Instantly share code, notes, and snippets.

@milkbread
Last active December 18, 2015 09:49
Show Gist options
  • Save milkbread/5763968 to your computer and use it in GitHub Desktop.
Save milkbread/5763968 to your computer and use it in GitHub Desktop.
HTML: simple arc-aggregation demonstration

D3 + TopoJSON -- Aggregetion

this is a first demonstration of my algorithm for aggregating adjacent polygons based on their redundant arc geometries

It is not working good.
But enables you to click on a feature ... which gets aggregated to the neighbor with the longest shared border!
<!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(https://gist.github.com/milkbread/5713683/raw/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>
<h1>Heading</h1>
<h1 class=sub>subheading</h1>
<div id=map></div>
<div>
<input type=text id=maxVal name=maxVal onChange=reShow(value) value=0>
</div>
<script>
var map = L.map('map').setView([49.36,7.29], 10);//.setView([49.643, 8.66], 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("/milkbread/raw/5754788/vg250_clipped_mini_topo.json", 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 featuresObjectsIndizes = []; //stores the IDs of all features ... to search the easier
var featuresObjects = pure_states.geometries.map(function(d){
var featu = new featureObj(d);
featuresObjectsIndizes.push(d.id)
return featu;
})
//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){console.log(data.id);
overLayer.removeAll();
doAggregation(data.id);
polygons = getGeometries_V2(featuresObjects, arcCollection)
overLayer.addGeometries(polygons,"path");
overLayer.showAll();
doStyling();
}
function doAggregation(id){
var test2 = featuresObjectsIndizes.indexOf(id);
var featureObject = featuresObjects[test2];
var polygons2 = [], removed_features = [];
console.log("###Begin the aggregation###")
var single_geoms = featureObject.getSingleGeometries();
console.log("This the id the of the analysed feature: ",featureObject.id)
var arcs = featureObject.getArcsPure();
console.log("These are my single geometries (without holes): ",single_geoms)
var neighbors = featureObject.getNeighbors(arcCollection);
console.log("These are my neighbors: ",neighbors)
//~~~~Different solutions are possible
var sorted_neighbors = sortArcs(neighbors, arcCollection)
var longest_neigh = sorted_neighbors[0];
console.log("This is the longest neighbor: ",longest_neigh, " ...as it is the first in an DESC-sorted array")
//~~~~~~~~~~~~~~~~
console.log("...that means we want to aggregate this feature: ",longest_neigh.id," (add to candidate)", " with this feature: ",featureObject.id, "(origin) ")
var addToCandidateIndex = featuresObjectsIndizes.indexOf(longest_neigh.id);
//-1 means ... nothing found ... that means ... search in the removed features array
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
addToCandidateIndex = featuresObjectsIndizes.indexOf(cacheOrigin.id_origin);//use the id of aggregrate (origin) feature to find the neighboring feature
}
var addToCandidate = featuresObjects[addToCandidateIndex];
console.log("...and with help of the index: "+addToCandidateIndex+" ...I can find the add to candidate: ",addToCandidate)
addToCandidate.aggregateFeature(featureObject, longest_neigh);
var test = featuresObjectsIndizes.indexOf(featureObject.id)
console.log("Did I find the origin to remove it: ",test)
console.log("Das array vorm Entfernen: ",featuresObjects.length)
//remove the -origin- feature from the array
var removed=featuresObjects.splice(test,1)
console.log(" ... und danach: ",featuresObjects.length," ... and the removed feature: ",removed)
//add removed feature to the storage of removed features
removedFeatureStorage.addRemFeat(featureObject, addToCandidate.id);
console.log("This is the storage of removed features ... is the new one here?! ",removedFeatureStorage.removedFeatures)
console.log("###Done the aggregation###")
//build the geometries using geometries in arcCollection
var test_geom = [];
}
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>
//adding an overlay to an existing leaflet map object
function mapOverlay(map_){
this.map=map_;
this.overlaySVG = d3.select(this.map.getPanes().overlayPane).append("svg");
this.overlay=this.overlaySVG.append("g").attr("class", "leaflet-zoom-hide")
var path_geo = d3.geo.path().projection(project);
//necessary for zooming the map...corresponded to: map.on("viewreset", reset);
this.resetView=resetView;
function resetView(bounds_map_){
var bottomLeft = project(bounds_map_[0]),
topRight = project(bounds_map_[1]);
this.overlaySVG.attr("width", topRight[0] - bottomLeft[0])
.attr("height", bottomLeft[1] - topRight[1])
.style("margin-left", bottomLeft[0] + "px")
.style("margin-top", topRight[1] + "px");
this.overlay.attr("transform", "translate(" + -bottomLeft[0] + "," + -topRight[1] + ")");
// this.showAll();
}
//show us all geometries that where added
this.showAll=showAll;
function showAll(){
this.features.attr("d",function(d){
var coords = d.coordinates, typ = d.type;
if (d.type==='Feature'){coords = d.geometry.coordinates; typ=d.geometry.type;}
//console.log(d)
if (d.type==='ArcString')typ='LineString';
var new_path = path_geo({type: typ, coordinates: coords})
return new_path;
})
}
//show us all geometries...filteres
this.showAllFiltered=showAllFiltered;
function showAllFiltered(maxVal){
var counter = [0,0,0]; //[features, points_all, points_filteres]
this.features.attr("d",function(d){
var coords = d.coordinates, typ = d.type;
if (d.type==='Feature'){coords = d.geometry.coordinates; typ=d.geometry.type;}
//console.log(d)
if (d.type==='ArcString')typ='LineString';
var new_path = path_geo({type: typ, coordinates: filtering(typ, coords)})
counter[0]++;
return new_path;
})
return counter;
function filtering(type, coords){
//console.log("test")
if (type == 'Polygon'){ coords = coords.map(mapLineString) }
else if (type == 'MultiPolygon'){coords = coords.map(mapPolygon) }
else if (type == 'MultiLineString'){coords = d.coords.map(mapLineString) }
return coords;
}
function mapPolygon(polygon){
return polygon.map(mapLineString);
}
function mapLineString(linestring){
return linestring.filter(filterPoints);
}
function filterPoints(point){
counter[1]++;
if (point.length<3 || point[2]>maxVal){ counter[2]++;
return point; }
}
}
//clean the overlay container
this.removeAll=removeAll;
function removeAll(){this.overlay.selectAll("path").remove();}
//add some geometries to the overlay
this.addGeometries=addGeometries;
function addGeometries(geoms_,path_ext){
if(path_ext===undefined)path_ext="path"
if (geoms_.length!==undefined){
this.features = this.overlay.selectAll(path_ext)
.data(geoms_)
.enter()
.append("path");
}else {
this.features = this.overlay
.append("path")
.datum(geoms_);
}
}
//projection to re-project overlay on the existing leaflet map
this.project=project;
function project(x) {
var point = this.map.latLngToLayerPoint(new L.LatLng(x[1], x[0]));
return [point.x, point.y];
}
}
//end of map overlay
//*****************
//get the arc-geometries...2nd version - using feature_objects
function getArcs_V2(topology, featureObjects_, simplify_){
var col_arcs_ = {};
featureObjects_.forEach(function(featureObj_){
var arcs = featureObj_.getArcsPure();
readArcs(arcs);
function readArcs(arcs_){
arcs_.forEach(function(arc){
var arc_id = arc;
var sign = 1;
if(arc_id<0){arc_id= (arc_id*(-1))-1; sign = -1;}
if((arc_id in col_arcs_)===false){
var arcs_cache = topojson.feature(topology, {type: 'LineString', arcs:[arc_id]});
arcs_cache.coordinates = arcs_cache.geometry.coordinates;
arcs_cache.members = [{id:featureObj_.id, direction:sign}]//, name:featureObj_.properties.GEN}]
arcs_cache.length = getLineLength(arcs_cache.geometry.coordinates)
//...simplify arc-geometries directly when specified
if (simplify_ !== undefined){
simplifyProcesses(arcs_cache, simplify_[0], simplify_[1])
}
//arcs_cache.sign = sign;
col_arcs_[arc_id]=arcs_cache;
}else {
col_arcs_[arc_id].members.push({id:featureObj_.id, direction:sign, name:featureObj_.properties.GEN})
}
})
}
})
return col_arcs_;
}
//end of get the arc-geometries
//*****************
//build geometries from arc-geometries...2nd version-using feature_objects
function getGeometries_V2(featObjs, col_arcs_){
var polygons = [], members = [];
featObjs.forEach(function(d){
if(d.type==='Polygon'){
members = [];
var a = readPolygon2({arcs:d.geometry}, d.id);
polygons.push({type:'Polygon', coordinates: a, id:d.id, clipped:d.clipped, properties: d.properties, neighbors: members, arcs:d.geometry})
}
else if(d.type==='MultiPolygon'){
members = [];
var a = d.geometry.map(function(e,i){return readPolygon2({arcs:d.geometry[i]},d.id)});
//console.log(d.id,members)
polygons.push({type:'MultiPolygon', coordinates: a, id:d.id, properties: d.properties, neighbors: members, arcs:d.geometry})
}
})
return polygons;
function readPolygon2(data, id){
var interPolys = [];
//loop the linestrings of the polygon
for (var i=0;i<data.arcs.length;i++){
//get the related 'LineString's by splitting at the start/end points (length === 4)
var poly_cache = [];
for (var j=0; j<data.arcs[i].length;j++){
var arc_id = data.arcs[i][j];
//avoid an unexplainable inconsistency within the dataset
//if(typeof(arc_id)!='number')arc_id=data.arcs[i][0][j];
var sign = 1;
if(arc_id<0){arc_id= (arc_id*(-1))-1; sign = -1;}
var arcs_cache2 = col_arcs_[arc_id].coordinates.slice();//--> das war der knackpunkt!!!!!!!!!!http://www.d-mueller.de/blog/javascript-arrays-kopieren/
if(col_arcs_[arc_id].members.length==2){
if(id==col_arcs_[arc_id].members[0].id){var c=col_arcs_[arc_id].members[1];c.arc_id=arc_id;members.push(c)}
else if(id==col_arcs_[arc_id].members[1].id){var c=col_arcs_[arc_id].members[0];c.arc_id=arc_id;members.push(c)}
}
if(sign===-1){arcs_cache2.reverse();}
//remove the last (it is redundant!!!) ...do only, when it is not the last LineString
if(j!==data.arcs[i].length-1){arcs_cache2.pop();}
//re-build the polygon to test this implementation
for (var x = 0;x<arcs_cache2.length;x++) poly_cache.push(arcs_cache2[x])
}
interPolys.push(poly_cache);
}
return interPolys;
}
}
//end of build
//****************
//old version of neighbor detection
function getArcsOfNeighbores(features, col_arcs_){
var members = [];
var feat_members = features.map(function(feature){
//clear the members array
members = members.slice(members.length);
if(feature.arcs!=undefined)var cache = feature.arcs;
else if (feature.geometry!=undefined)var cache = feature.geometry;
if(feature.type==='Polygon'){
readPolygon2({arcs:cache}, feature.id);
//console.log(members)
}
else if(feature.type==='MultiPolygon'){
cache.map(function(e,i){return readPolygon2({arcs:cache[i]},feature.id)});
//console.log(members)
}
return members;
});
return feat_members;
function readPolygon2(data, id){
// console.log(data.arcs)
//loop the linestrings of the polygon
for (var i=0;i<data.arcs.length;i++){
// console.log(data.arcs[i])
for (var j=0; j<data.arcs[i].length;j++){
var arc_id = data.arcs[i][j];
if(arc_id<0){arc_id= (arc_id*(-1))-1;}
// console.log(data.arcs[i][j], col_arcs_)
if(col_arcs_[arc_id].members.length==2){
if(id==col_arcs_[arc_id].members[0].id){var c=col_arcs_[arc_id].members[1];c.arc_id=arc_id;members.push(c)}
else if(id==col_arcs_[arc_id].members[1].id){var c=col_arcs_[arc_id].members[0];c.arc_id=arc_id;members.push(c)}
}
}
}
}
}
//****************
//new version for neighbor detection ... modular=read array of features or single features
function getNeighborsOfArcs(featuresObjs_, arcCollection_){
var members = [];
featuresObjs_.forEach(function(featurObj){
var feat_members = getNeighborsOfFeature(featurObj, arcCollection_);
members.push(feat_members)
})
return members;
}
function getNeighborsOfFeature(featurObj, arcCollection_){
var feat_members = [], allArcs = featurObj.getArcsPure(), id = featurObj.id;
allArcs.forEach(function(arc){
var arc_id = arc;
if(arc_id<0){arc_id= (arc_id*(-1))-1;}
var arcObject_members = arcCollection_[arc_id].members;
if(arcObject_members.length==2){
if(id==arcObject_members[0].id) var c=arcObject_members[1];
else if(id==arcObject_members[1].id) var c=arcObject_members[0];
c.arc_id=arc_id;
feat_members.push(c)
}
})
return feat_members;
}
//object for removed features
function remFeatures(removeCandidate, id_origin_){
this.id=removeCandidate.id;
this.id_origin=id_origin_; //this is the id of the feature, where this was aggregated to
//this.index=index_;
}
function remFeatureStorage(){
this.removedFeatures = [];
var removedFeaturesIndizes = [];
this.addRemFeat=addRemFeat;
function addRemFeat(remFeature_, id_origin_){
var remFeature = new remFeatures(remFeature_, id_origin_);
this.removedFeatures.push(remFeature);
}
this.getIndizes=getIndizes;
function getIndizes(){
removedFeaturesIndizes = this.removedFeatures.map(function(d){return d.id});
return removedFeaturesIndizes;
}
}
//Object-definition -- Feature-Object ... contains all necessary functions and variables of one feature:
//Type, ID, PROPERTIES, GEOMETRY, getArcsPure(), getGeometry(), getNeighbors()
function featureObj(feature_){
//this.feature = feature_;
this.type = feature_.type;
this.id = feature_.id;
this.properties = feature_.properties;
this.geometry = feature_.arcs;
this.clipped = false;
//check if geometry has holes
this.has_hole = false;
if(this.type=='Polygon'){
if (this.geometry.length==2)this.has_hole = true;
}
else if(this.type=='MultiPolygon'){
this.geometry.forEach(function(polygonGeom){
if(polygonGeom.length==2)this.has_hole = true;
})
}
//***FUNCTIONS***
//get all neighbors of this feature ... fundamentally based on 'getNeighborsOfFeature()'
this.getNeighbors=getNeighbors;
function getNeighbors(arcCollection__){
return getNeighborsOfFeature(this, arcCollection__)
}
//get all arcs (pure) in one array...'arcs'
this.getArcsPure=getArcsPure;
function getArcsPure(){
var pure_arcs = [];
if(this.type=='Polygon')pure_arcs = readPoly(this.geometry,'arcs');
else if (this.type=='MultiPolygon') {
this.geometry.forEach(function(polygon0){pure_arcs=pure_arcs.concat(readPoly(polygon0,'arcs'))})
}
return pure_arcs;
}
//get polygons singulary...'single'
this.getSingleGeometries=getSingleGeometries;
function getSingleGeometries(){
var single_geoms = [];
if(this.type=='Polygon')single_geoms = readPoly(this.geometry,'single');
else if (this.type=='MultiPolygon') {
this.geometry.forEach(function(polygon0){single_geoms.push(readPoly(polygon0,'single')); })
}
return single_geoms;
}
//aggregate a feature with this
this.aggregateFeature=aggregateFeature;
function aggregateFeature(remFeature, neighArc){
console.log("This is my -add to- geometry: ", this.geometry," ... this is the -origin- geometry: ", remFeature.geometry," ... and this is the neighbor arc: ",neighArc)
console.log("Hole in the -add to- geometry? ", this.has_hole," ... hole in the -origin- geometry: ", remFeature.has_hole)
if(this.type=='Polygon'){
var reformedGeom = reformPolygonArcs2(neighArc.direction, neighArc.arc_id, remFeature.geometry).slice();
console.log("This is the reformed -origin- geometry: ",reformedGeom)
//find the corresponding arc in this geometry
if (neighArc.direction == 1)var replace_id = neighArc.arc_id;
else if (neighArc.direction == -1)var replace_id = (neighArc.arc_id+1)*(-1);
var arcIndex = this.geometry[0].indexOf(replace_id)
console.log("This is the index of the arc (",replace_id,"), in the -add to- geometry: ",arcIndex," ... proof it: ", this.geometry)
var new_composition = reCombinateArcs(this.geometry[0], arcIndex, reformedGeom)
console.log("This is the re-combined outer ring of this geometry (polygon): ",new_composition)
this.geometry[0]=new_composition; //just replace the outer ring ... by that we simply keep the holes
//add the holes of the -origin- geometry to the reformed geometry...if some exist
if(remFeature.has_hole==true){
for(var i=1;i<remFeature.geometry.length;i++){
this.geometry.push(remFeature.geometry[i])
}
}
} else alert("Other geometries than Polygon, are not implemented so far")
this.clipped=true;
return remFeature;
}
//add the reformed ('redi_geom_') geometry to the -add to- geometry ('feature')
function reCombinateArcs(feature, arc_index_, redi_geom_){
//when at position 0 --> [reformed arcs, original arcs {1...End}]
if (arc_index_ == 0){
var new_composition_ = redi_geom_;
new_composition_ = new_composition_.concat( feature.slice(1));
//when at any position X --> [original arcs {0...X-1}, reformed arcs, original arcs {X+1...End}]
}else { var new_composition_ = feature.slice(0,arc_index_);
new_composition_ = new_composition_.concat( redi_geom_);
new_composition_ = new_composition_.concat(feature.slice(arc_index_+1));
}
return new_composition_
}
function readPoly(polygon_parts, origin){
if(origin=='arcs'){
var arcs = [];
polygon_parts.forEach(function(polygon){
polygon.forEach(function(arc){arcs.push(arc)})
})
return arcs;
}
else if(origin=='single'){
//var single = [];
//console.log(polygon_parts);
//polygon_parts.forEach(function(part){single.push(part)})
//TODO: needs an additional processing for the holes of a polygon --> polygon_parts[1] - polygon_parts[length-1]
//use only the outer ring
return polygon_parts[0];
}
}
}
function reformPolygonArcs2(direction, arc_id, arcs){
if (direction == -1)var replace_id0 = arc_id;
else if (direction == 1)var replace_id0 = (arc_id+1)*(-1);
return editPolygon_(replace_id0, arcs);
function editPolygon_(id, arcs){
//get the indizes ...
var poly_index = 0, //poly_index=0--> we only need the outer ring
arc_index = arcs[poly_index].indexOf(id); //arc_index is the position of the arc in the array of the outer ring
//console.log(id, arcs[poly_index],arcs[poly_index][arc_index])
if (arc_index == 0)var de_composition = arcs[poly_index].slice(1);
else { var de_composition = arcs[poly_index].slice(arc_index+1);
de_composition = de_composition.concat(arcs[poly_index].slice(0,arc_index));
}
//console.log("de_composition of arcs: ",de_composition)
return de_composition
}
}
//get the length of a polygon only from the lengths of each arcs, which it is consists of
function getPolyLengthFromArcs(arcs_, arcCollection_){
//console.log(arcs_)
var length_ = 0;
for (var i=0; i<arcs_.length; i++){
var arc_id = arcs_[i];
if(arc_id<0)arc_id=(arc_id*(-1))-1;
length_ = length_ + arcCollection_[arc_id].length;
}
return length_;
}
//************
//get Length of a linestring [[coordsX1,coordsY1],...,[coordsXn,coordsYn]]
function getLineLength(coords){
var length = 0;
//coords.forEach(function(d){
for (var i=1;i<coords.length;i++){
var a = coords[i-1], b = coords[i], dX = a[0]+b[0], dY = a[1]+b[1];
length = length + Math.sqrt(Math.pow(dX,2)+Math.pow(dY,2));
}
return length;
}
//************
//simplify and filter arc-geometries
function simplifyArcs(col_arcs_, simplify_, max_val){
for(arcs in col_arcs_){
simplifyProcesses(col_arcs_[arcs], simplify_, max_val)
}
return col_arcs_;
}
function simplifyProcesses(arc, simplify_, max_val){
arc.type='LineString';
simplify_(arc)
var simple_arc = arc.coordinates.filter(call_filterLine)
arc.coordinates=simple_arc;
function call_filterLine(data){
return filterLine(data, max_val)
}
}
function filterLine(data, max_val){
if(data.length===2 ||data[2]===0 || data[2]>max_val)
//console.log(data)
return data
}
//end of simplify arc-geometries
//************
function filterSimplifiedArcs(col_arcs_, max_val){
for(arcs in col_arcs_){
var arc = col_arcs_[arcs];
var simple_arc = arc.coordinates.filter(call_filterLine)
arc.coordinates=simple_arc;
}
return col_arcs_;
function call_filterLine(data){
return filterLine(data, max_val)
}
}
//get the triangle values of the generalized arc-geometries
function getTriangleSizes(col_arcs_){
var max = 0, min = 100000000;//,allTriangleSizes = [];
for (arcs in col_arcs_){
col_arcs_[arcs].geometry.coordinates.forEach(function(d){
if(d.length >= 3 ){
//allTriangleSizes.push(d[2])
if (d[2]<min)min=d[2];
if(d[2]>max)max=d[2];
}
})
}
return [min, max]
}
//replace all german umlaute within a given string
function replaceUmlaute(value){
var id = value;
var umlaute = {'\u00c4':'Ae', '\u00e4':"ae", '\u00d6':'Oe', '\u00f6': 'oe', '\u00dc':'Ue', '\u00fc':'ue', '\u00df':'ss'}
for(i in umlaute){if(id.indexOf(i)!=-1)id=id.replace(i,umlaute[i])}
return id;
}
//***********************
//ArcClipping - Functions
function findLongestArc(neigh_arcs, arcCollection_){
var longest = {}, longest_neigh_ = {}, test = false, list = [];
neigh_arcs.forEach(function(e){
if (test == false){test=true; longest=arcCollection_[e.arc_id]; longest_neigh_=e;}
else if(arcCollection_[e.arc_id].length>longest.length){longest = arcCollection_[e.arc_id];longest_neigh_=e;}
})
return longest_neigh_;
}
//was 'findLongestArc2' before renaming
function sortArcs(neigh_arcs, arcCollection_){
var list = neigh_arcs.map(function(a){
//a.length =arcCollection_[a.arc_id].length;
return a;})
list.sort(function sortfunction(a, b){return (arcCollection_[b.arc_id].length - arcCollection_[a.arc_id].length)})
//console.log('list-sorted: ', list)
return list;
}
function reformPolygonArcs(direction, arc_id, arcs, type){
if (direction == -1)var replace_id0 = arc_id;
else if (direction == 1)var replace_id0 = (arc_id+1)*(-1);
if (type==undefined)type='Polygon';
if(type=='Polygon'){
return editPolygon_(replace_id0, arcs);
}else if(type=='MultiPolygon'){
alert('Reforming MultiPolygonal Features is not implemented, so far!')
stop();
}
function editPolygon_(id, arcs){
var found = false;
var poly_index, arc_index;
//find the indizes
arcs.forEach(function(arc,i){
if (arc.indexOf(id) != -1){
poly_index = i, arc_index = arc.indexOf(id);
found = true;
}
})
if(found===true){
//console.log(id, arcs[poly_index],arcs[poly_index][arc_index])
if (arc_index == 0)var de_composition = arcs[poly_index].slice(1);
else { var de_composition = arcs[poly_index].slice(arc_index+1);
de_composition = de_composition.concat(arcs[poly_index].slice(0,arc_index));
}
//console.log("de_composition of arcs: ",de_composition)
return de_composition
}
}
}
//clip the reformed arcs of the 'to-clip-feature' to the 'clip-to-feature'
function clipArcs(direction, arc_id, corresp_feat_, redi_geom_){
console.log(direction, arc_id, corresp_feat_, redi_geom_)
var arcGeom = corresp_feat_.arcs;
for(var u=0;u<arc_id.length;u++){
//re-define the arc-id...to find it
if (direction[u] == 1)var replace_id = arc_id[u];
else if (direction[u] == -1)var replace_id = (arc_id[u]+1)*(-1);
//if 'clip-to-feature' is a POLYGON
if (corresp_feat_.type == 'Polygon'){
var poly_index, arc_index, polygon = arcGeom;//old version: corresp_feat_.arcs;
getPolygonIndizes(polygon); //called without index = POLYGON
var new_composition = reCombinateArcs(polygon[poly_index], arc_index)
//console.log("new_composition: ",new_composition)
polygon[poly_index]=new_composition;
//console.log("polygon: ",polygon)
//return polygon
//define the arcs of the geometry
arcGeom = polygon;
//if 'clip-to-feature' is a MULTIPOLYGON
}else if (corresp_feat_.type == 'MultiPolygon'){
var multi_poly_index, poly_index, arc_index, multi_poly = arcGeom;//old version: corresp_feat_.arcs;
//console.log(corresp_feat_.arcs);
var found = false;
multi_poly.forEach(function(poly,count){
if (found===true)return;
//console.log(poly);
found = getPolygonIndizes(poly, count); //called withindex = MULTIPOLYGON
})
//console.log("final multi indizes: ",multi_poly_index, poly_index, arc_index)
var new_composition = reCombinateArcs(multi_poly[multi_poly_index][poly_index], arc_index)
//console.log("new_composition: ",new_composition)
multi_poly[multi_poly_index][poly_index]=new_composition;
//console.log("multi_polygon: ",multi_poly)
//return multi_poly
//define the arcs of the geometry
arcGeom = multi_poly;
}
}
return arcGeom;
//function to find the positions, where the redundant arc can be found
function getPolygonIndizes(polygon_, index){ //index...is needed for the differentiation between MULTI- & POLYGON
var found_ = false;
polygon_.forEach(function(d,i){
if (found_===true)return;
if(d.indexOf(replace_id)!=-1){
//console.log("rest: ",replace_id,d, d.indexOf(replace_id), d[d.indexOf(replace_id)])
poly_index = i, arc_index = d.indexOf(replace_id);
if (index!=undefined)multi_poly_index = index;
found_=true;
}
})
return found_;
}
//add the reformed arcs to the 'clip-to-feature'
function reCombinateArcs(feature, arc_index_){
//when at position 0 --> [reformed arcs, original arcs {1...End}]
if (arc_index_ == 0){
var new_composition_ = redi_geom_;
new_composition_ = new_composition_.concat( feature.slice(1));
//when at any position X --> [original arcs {0...X-1}, reformed arcs, original arcs {X+1...End}]
}else { var new_composition_ = feature.slice(0,arc_index_);
new_composition_ = new_composition_.concat( redi_geom_);
new_composition_ = new_composition_.concat(feature.slice(arc_index_+1));
}
return new_composition_
}
}
function polygonArea(polygon__) //http://www.mathopenref.com/coordpolygonarea2.html
{ numPoints = polygon__.length;
area = 0; // Accumulates area in the loop
j = numPoints-1; // The last vertex is the 'previous' one to the first
for (i=0; i<numPoints; i++)
{
X1 = polygon__[i][0], Y1 = polygon__[i][1];
X2 = polygon__[j][0], Y2 = polygon__[j][1];
area = area + (X1+X2) * (Y1-Y2);
j = i; //j is previous vertex to i
}
return area/2;
}
function RKMapping_version(){
return "0.4.3"
}
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment