Files
secondo/Algebras/OSM/Scripts/TuDetermineSections.sec
2026-01-23 17:03:45 +08:00

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;