386 lines
13 KiB
Plaintext
386 lines
13 KiB
Plaintext
################################################################################
|
|
### Determing Sections From imported OSM data (5 / 11)
|
|
################################################################################
|
|
### Description:
|
|
### - This script determines Sections within Streets.
|
|
### Please, see tu_Osm_import.sh for further details.
|
|
###
|
|
### Preconditions:
|
|
### - activated necessary algebras
|
|
### - existing open database with successfully imported Osm data
|
|
### - ExtStreetsRel-relation
|
|
### ExtStreetsRel: rel{GeoData: sline, StreetId: int, Name: string,
|
|
### Ref: string, RoadClassRef: int, OneWay: int,
|
|
### Bridge: int, MaxSpeed: int, Tunnel: bool,
|
|
### Layer: int, GroupId: int}
|
|
### - RestrictionsRel-relation
|
|
### RestrictionsRel: rel{FromStreet: int, ToStreet: int, ViaPoint: point,
|
|
### Restriction: text}
|
|
###
|
|
### Postconditions:
|
|
### - already existing relations
|
|
### - ExtSectionsRel-relation
|
|
### ExtSectionsRel: rel{SectionId: int, Section: sline, StartNodeId: int,
|
|
### EndNodeId: int, StreetId: int, GroupId: int,
|
|
### SectionDist: real}
|
|
### - NodesRel-relation
|
|
### NodesRel: rel{Node: point, NodeId: int}
|
|
### - OnlyRestrictions
|
|
### OnlyRestrictions: rel{FromStreeRef: int, ToStreetRef: int,
|
|
### ViaNodeRef: int, ViaNode: point,
|
|
### Only: bool, Restriction: text}
|
|
### - NoUturnRestrictions
|
|
### NoUturnRestrictions: rel{FromStreeRef: int, ToStreetRef: int,
|
|
### ViaNodeRef: int, ViaNode: point,
|
|
### NoUturn: bool}
|
|
### - NoLeftTurnRestrictions
|
|
### NoLeftTurnRestrictions: rel{FromStreeRef: int, ToStreetRef: int,
|
|
### ViaNodeRef: int, ViaNode: point,
|
|
### NoLeftTurn: bool}
|
|
### - NoRightTurnRestrictions
|
|
### NoRightTurnRestrictions: rel{FromStreeRef: int, ToStreetRef: int,
|
|
### ViaNodeRef: int, ViaNode: point,
|
|
### NoRightTurn: bool}
|
|
### - NoStraightOnRestrictions
|
|
### NoStraightOnRestrictions: rel{FromStreeRef: int, ToStreetRef: int,
|
|
### ViaNodeRef: int, ViaNode: point,
|
|
### NoStraightOn: bool}
|
|
###
|
|
### Author:
|
|
### - Thomas Uchdorf, thomas.uchdorf(at)fernuni-hagen.de
|
|
################################################################################
|
|
|
|
# Computing all junctions and terminating points by finding the existing
|
|
# crossings between Streets and adding terminating points
|
|
#let juncTermPts =
|
|
# (ExtStreetsRel feed
|
|
# project [StreetId,GeoData,Layer] {s1}
|
|
# ExtStreetsRel feed
|
|
# project [StreetId,GeoData,Layer] {s2}
|
|
# spatialjoin [GeoData_s1, GeoData_s2]
|
|
# filter[(.StreetId_s1 < .StreetId_s2) and (.Layer_s1 = .Layer_s2)]
|
|
# projectextend[; CrossRoads: crossings(.GeoData_s1, .GeoData_s2)]
|
|
# filter[not(isempty(.CrossRoads))]
|
|
# aggregateB[CrossRoads;
|
|
# fun(P1: points, P2: points) P1 union P2;
|
|
# [const points value ()]])
|
|
# union
|
|
# (ExtStreetsRel feed
|
|
# projectextend[; B : boundary(toline(.GeoData))]
|
|
# aggregateB[B;
|
|
# fun(P3 : points, P4 : points) P3 union P4;
|
|
# [const points value ()]]
|
|
# );
|
|
let SectionPtsTmp =
|
|
(ExtStreetsRel feed
|
|
project [StreetId,GeoData,Layer] {s1}
|
|
ExtStreetsRel feed
|
|
project [StreetId,GeoData,Layer] {s2}
|
|
spatialjoin [GeoData_s1, GeoData_s2]
|
|
filter[(.StreetId_s1 < .StreetId_s2) and (.Layer_s1 = .Layer_s2)]
|
|
filter[.GeoData_s1 intersects .GeoData_s2]
|
|
projectextend[;
|
|
Road1: .StreetId_s1,
|
|
Road2: .StreetId_s2,
|
|
CrossRoads: crossings(.GeoData_s1, .GeoData_s2)]
|
|
filter[(isdefined(.CrossRoads)) and (not(isempty(.CrossRoads)))]
|
|
projectextendstream [Road1,Road2; Pt: components(.CrossRoads)])
|
|
(ExtStreetsRel feed
|
|
projectextend [;
|
|
Road1: .StreetId,
|
|
Road2: .StreetId,
|
|
B: boundary(toline(.GeoData))]
|
|
projectextendstream [Road1,Road2; Pt: components(.B)]
|
|
)
|
|
concat
|
|
consume;
|
|
let StSecPts =
|
|
(SectionPtsTmp feed
|
|
projectextend [Pt; Street: .Road1]
|
|
SectionPtsTmp feed
|
|
projectextend [Pt; Street: .Road2]
|
|
concat
|
|
sortby [Street,Pt]
|
|
rdup
|
|
sortby [Street]
|
|
groupby [Street;
|
|
SecPts: group feed
|
|
projecttransformstream [Pt]
|
|
collect_points [TRUE]]
|
|
consume);
|
|
#let SectionPtsRel =
|
|
# (SectionPtsTmp feed
|
|
# ExtStreetsRel feed
|
|
# project [StreetId,GeoData] {s1}
|
|
# hashjoin [Road1,StreetId_s1,99997])
|
|
# ExtStreetsRel feed
|
|
# project [StreetId,GeoData] {s2}
|
|
# hashjoin[Road2,StreetId_s2,99997]
|
|
# filter [((.Road1=.Road2) and
|
|
# (.Pt inside toline(.GeoData_s1)) and
|
|
# (distance(.Pt,.GeoData_s1) = 0)) or
|
|
# (not(.Road1=.Road2) and
|
|
# (.Pt inside toline(.GeoData_s1)) and
|
|
# (.Pt inside toline(.GeoData_s2)) and
|
|
# (distance(.Pt,.GeoData_s1) = 0) and
|
|
# (distance(.Pt,.GeoData_s2) = 0))]
|
|
# extend [
|
|
# dist1:
|
|
# ifthenelse(.Road1=.Road2,
|
|
# 0.,atpoint(.GeoData_s1,.Pt,TRUE)),
|
|
# dist2:
|
|
# ifthenelse(.Road1=.Road2,
|
|
# size(.GeoData_s1),atpoint(.GeoData_s2,.Pt,TRUE))]
|
|
# sortby [Road1,dist1,dist2]
|
|
# addcounter[SectionId,1]
|
|
# consume;
|
|
|
|
# Splitting up all Streets inTo Sections
|
|
let StsPlusSecsTmp =
|
|
StSecPts feed {a}
|
|
ExtStreetsRel feed
|
|
projectextend [;
|
|
GroupId: .GroupId,
|
|
StreetId: .StreetId,
|
|
Street: .GeoData,
|
|
UndirStreet: toline(.GeoData)]
|
|
hashjoin [Street_a,StreetId,99997]
|
|
projectextendstream [GroupId,StreetId,Street;
|
|
Section: (.UndirStreet polylines [FALSE,.SecPts_a])]
|
|
consume;
|
|
|
|
# Creating a relation for the Sections by removing duplicates
|
|
let SectionsTmp =
|
|
StsPlusSecsTmp feed
|
|
project [Section]
|
|
sortby [Section]
|
|
rdup
|
|
addcounter[SectionId, 1]
|
|
extend [Pts: boundary(.Section)]
|
|
projectextend [SectionId, Section;
|
|
Help: Fromline(.Section),
|
|
Node1: get(.Pts,0),
|
|
Node2: get(.Pts,1)]
|
|
consume;
|
|
|
|
# Removing the help points
|
|
#delete juncTermPts;
|
|
|
|
# Removing the help relations
|
|
delete SectionPtsTmp;
|
|
delete StSecPts;
|
|
|
|
# Collecting all Nodes (junctions and end points) in one point array and
|
|
# adding IDs To the Nodes To form a relation
|
|
let NodesRel =
|
|
components(
|
|
SectionsTmp feed
|
|
projectextend[; EndPoints: boundary(.Section)]
|
|
aggregateB[EndPoints;
|
|
fun(P1: points, P2: points) P1 union P2 ;
|
|
[const points value ()]])
|
|
Namedtransformstream [Node]
|
|
addcounter [NodeId,1]
|
|
consume;
|
|
|
|
# Adding indexes for faster access
|
|
derive NodesRel_NodeId_btree =
|
|
NodesRel createbtree[NodeId];
|
|
derive NodesRel_Node_rtree =
|
|
NodesRel creatertree[Node];
|
|
|
|
# Combining source and destination points with Sections between them
|
|
# (adding References To Nodes)
|
|
# SectionsRel: rel{SectionId: int, Section: line, Node1: point,
|
|
# Node2: point, Node1Id: int, Node2Id: int}
|
|
let SectionsRel =
|
|
(SectionsTmp feed
|
|
NodesRel feed {a}
|
|
hashjoin[Node1, Node_a, 99997])
|
|
NodesRel feed {b}
|
|
hashjoin[Node2, Node_b, 99997]
|
|
projectextend [SectionId, Section, Help, Node1, Node2;
|
|
Node1Id: .NodeId_a, Node2Id: .NodeId_b]
|
|
consume;
|
|
|
|
# Removing the help relation
|
|
delete SectionsTmp;
|
|
|
|
# Adding indexes for faster access
|
|
derive SectionsRel_SectionId_btree =
|
|
SectionsRel createbtree[SectionId];
|
|
derive SectionsRel_Node1Id_btree =
|
|
SectionsRel createbtree[Node1Id];
|
|
derive SectionsRel_Node2Id_btree =
|
|
SectionsRel createbtree[Node2Id];
|
|
derive SectionsRel_Section_rtree =
|
|
SectionsRel creatertree[Section];
|
|
|
|
# Creating a relation that enables linking Sections To additional Street
|
|
# data like speed limits or Names and combining the order by group ID,
|
|
# Street ID and distance on Street with the Section ID
|
|
let ExtSectionsRel =
|
|
(StsPlusSecsTmp feed
|
|
projectextend [GroupId,StreetId,Street; Part: .Section]
|
|
SectionsRel feed
|
|
hashjoin [Part,Section,99997]
|
|
remove [Part,Section]
|
|
extend [
|
|
Node1Dist: atpoint(.Street,.Node1,TRUE),
|
|
Node2Dist: atpoint(.Street,.Node2,TRUE)]
|
|
extend [startNode:
|
|
ifthenelse(.Node1Dist < .Node2Dist, .Node1, .Node2),
|
|
endNode:
|
|
ifthenelse(.Node1Dist < .Node2Dist, .Node2, .Node1),
|
|
StartNodeId:
|
|
ifthenelse(.Node1Dist < .Node2Dist, .Node1Id, .Node2Id),
|
|
EndNodeId:
|
|
ifthenelse(.Node1Dist < .Node2Dist, .Node2Id, .Node1Id)]
|
|
extend [
|
|
LowerStreetDist: ifthenelse(.Node1Dist < .Node2Dist,
|
|
.Node1Dist, .Node2Dist),
|
|
HigherStreetDist: ifthenelse(.Node1Dist < .Node2Dist,
|
|
.Node2Dist, .Node1Dist),
|
|
SectionDist: size(.Help)]
|
|
extend [Section:
|
|
ifthenelse(
|
|
.SectionDist = .HigherStreetDist,
|
|
set_startsmaller(.Help,
|
|
get_startsmaller(.Street)),
|
|
set_startsmaller(.Help,
|
|
get_startsmaller(create_sline(.StartNode,.EndNode))))]
|
|
project[
|
|
GroupId, StreetId, SectionId, Section, StartNodeId, EndNodeId,
|
|
LowerStreetDist,HigherStreetDist,SectionDist])
|
|
remove [SectionId]
|
|
sortby [GroupId,StreetId,HigherStreetDist,LowerStreetDist]
|
|
addcounter[SectionId, 1]
|
|
# remove [StreetDist]
|
|
consume;
|
|
|
|
# Postprocessing Streets that start and end in the same point
|
|
# (their Sections are computed in a wrong way, since their start and end
|
|
# point as well as their positions on the Street can not be distinguished
|
|
# separately)
|
|
#...
|
|
update ExtSectionsRel :=
|
|
(((((ExtStreetsRel feed
|
|
extend [
|
|
StreetStartNode: atposition(.GeoData,0.0,TRUE),
|
|
StreetEndNode: atposition(.GeoData,size(.GeoData),TRUE)]
|
|
filter [.StreetStartNode = .StreetEndNode]
|
|
ExtSectionsRel feed
|
|
hashjoin [StreetId,StreetId,99997])
|
|
ExtSectionsRel feed {a}
|
|
hashjoin [StreetId,StreetId_a,99997]
|
|
filter [(.HigherStreetDist = .HigherStreetDist_a) and
|
|
(.SectionId < .SectionId_a)])
|
|
NodesRel feed {e}
|
|
hashjoin [StreetStartNode,Node_e,99997]
|
|
remove [Node_e])
|
|
NodesRel feed {f}
|
|
hashjoin [StreetEndNode,Node_f,99997]
|
|
remove [Node_f]
|
|
extend [StreetStartNodeId: .NodeId_e,StreetEndNodeId: .NodeId_f]
|
|
projectextend [GroupId,StreetId,SectionId;
|
|
NewSection: set_startsmaller(.Section,not(get_startsmaller(.Section))),
|
|
NewStartNodeId: .StreetStartNodeId,
|
|
NewEndNodeId: .StartNodeId,
|
|
NewHigherStreetDist: .LowerStreetDist,
|
|
NewLowerStreetDist: .HigherStreetDist,
|
|
NewSectionDist: .SectionDist] {n})
|
|
ExtSectionsRel feed
|
|
smouterjoin [SectionId_n,SectionId]
|
|
projectextend [GroupId,StreetId;
|
|
Section:
|
|
ifthenelse(isdefined(.SectionId_n),.NewSection_n,.Section),
|
|
StartNodeId:
|
|
ifthenelse(isdefined(.SectionId_n),.NewStartNodeId_n,.StartNodeId),
|
|
EndNodeId:
|
|
ifthenelse(isdefined(.SectionId_n),.NewEndNodeId_n,.EndNodeId),
|
|
LowerStreetDist:
|
|
ifthenelse(isdefined(.SectionId_n),
|
|
.NewLowerStreetDist_n,.LowerStreetDist),
|
|
HigherStreetDist:
|
|
ifthenelse(isdefined(.SectionId_n),
|
|
.NewHigherStreetDist_n,.HigherStreetDist),
|
|
SectionDist:
|
|
ifthenelse(isdefined(.SectionId_n),
|
|
.NewSectionDist_n,.SectionDist)]
|
|
sortby [GroupId,StreetId,HigherStreetDist,LowerStreetDist]
|
|
addcounter[SectionId, 1]
|
|
consume);
|
|
|
|
# Removing the help relations
|
|
delete SectionsRel;
|
|
delete StsPlusSecsTmp;
|
|
|
|
# Adding indexes for faster access
|
|
derive ExtSectionsRel_SectionId_btree =
|
|
ExtSectionsRel createbtree[SectionId];
|
|
derive ExtSectionsRel_StartNodeId_btree =
|
|
ExtSectionsRel createbtree[StartNodeId];
|
|
derive ExtSectionsRel_EndNodeId_btree =
|
|
ExtSectionsRel createbtree[EndNodeId];
|
|
derive ExtSectionsRel_StreetId_btree =
|
|
ExtSectionsRel createbtree[StreetId];
|
|
derive ExtSectionsRel_GroupId_btree =
|
|
ExtSectionsRel createbtree[GroupId];
|
|
derive ExtSectionsRel_Section_rtree =
|
|
ExtSectionsRel creatertree[Section];
|
|
|
|
#let StreetToNumSections =
|
|
# ExtSectionsRel feed
|
|
# sortby [StreetId]
|
|
# groupby [StreetId; NumSections: group count]
|
|
# consume;
|
|
|
|
# Extending the Restrictions-relation by References To the junction points
|
|
let ExtRestrictionsRel =
|
|
RestrictionsRel feed
|
|
NodesRel feed
|
|
hashjoin [ViaPoint,Node,99997]
|
|
extend [FromStreetRef: .FromStreet, ToStreetRef: .ToStreet,
|
|
ViaNodeRef: .NodeId, ViaNode: .ViaPoint]
|
|
remove [FromStreet, ToStreet, ViaPoint, NodeId, Node]
|
|
consume;
|
|
|
|
# Removing the help relation
|
|
delete RestrictionsRel;
|
|
|
|
# Splitting up the Restrictions relation and distributing the Restrictions To
|
|
# different relations
|
|
let OnlyRestrictions =
|
|
ExtRestrictionsRel feed
|
|
extend [Only: .Restriction starts "Only"]
|
|
filter [.Only]
|
|
remove [OsmId,RestrictionId]
|
|
consume;
|
|
# restrictive Restrictions have To be viewed separately since they otherwise
|
|
# multiply tuples in conjunction with crossings
|
|
let NoUturnRestrictions =
|
|
ExtRestrictionsRel feed
|
|
filter [.Restriction = "no_u_turn"]
|
|
extend [NoUturn: TRUE]
|
|
remove [OsmId,Restriction,RestrictionId]
|
|
consume;
|
|
let NoLeftTurnRestrictions =
|
|
ExtRestrictionsRel feed
|
|
filter [.Restriction = "no_left_turn"]
|
|
extend [NoLeftTurn: TRUE]
|
|
remove [OsmId,Restriction,RestrictionId]
|
|
consume;
|
|
let NoStraightOnRestrictions =
|
|
ExtRestrictionsRel feed
|
|
filter [.Restriction = "no_straight_on"]
|
|
extend [NoStraightOn: TRUE]
|
|
remove [OsmId,Restriction,RestrictionId]
|
|
consume;
|
|
let NoRightTurnRestrictions =
|
|
ExtRestrictionsRel feed
|
|
filter [.Restriction = "no_right_turn"]
|
|
extend [NoRightTurn: TRUE]
|
|
remove [OsmId,Restriction,RestrictionId]
|
|
consume;
|
|
|