From 3ffd3ed3627dffd882cc5851579b5de9340ede01 Mon Sep 17 00:00:00 2001 From: Rutvik Patel Date: Fri, 19 May 2023 16:29:20 +0530 Subject: [PATCH] scripts: seattle network helpers --- .../python/scripts/remove_duplicate_links.py | 33 ++++++ .../scala/scripts/ConsolidateOSMNodes.scala | 101 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/main/python/scripts/remove_duplicate_links.py create mode 100644 src/main/scala/scripts/ConsolidateOSMNodes.scala diff --git a/src/main/python/scripts/remove_duplicate_links.py b/src/main/python/scripts/remove_duplicate_links.py new file mode 100644 index 00000000000..1a129fbaa58 --- /dev/null +++ b/src/main/python/scripts/remove_duplicate_links.py @@ -0,0 +1,33 @@ +import sys +import shapefile + +if len(sys.argv) != 4: + print("python remove_duplicate_links.py ") + exit() + +reader = shapefile.Reader(sys.argv[2]) + +writer = shapefile.Writer(sys.argv[3]) + +writer.field('ID', 'C', 20, 0) +writer.field('MODES', 'C', 64, 0) +writer.field('LANES', 'N', 35, 7) +writer.field('DATA1', 'N', 35, 7) # hourly capacity per lane +writer.field('DATA2', 'C', 35, 7) # add mph + +s = set() +for n in reader.iterShapeRecords(): + record = n.record + shape = n.shape + if record['ID'] not in s: + s.add(f"{record['JNODE']}-{record['INODE']}") + writer.record( + record['ID'], + record['MODES'], + record['LANES'], + record['DATA1'], + str(record['DATA2']) + " mph", + ) + writer.shape(shape) + +writer.close() diff --git a/src/main/scala/scripts/ConsolidateOSMNodes.scala b/src/main/scala/scripts/ConsolidateOSMNodes.scala new file mode 100644 index 00000000000..88ec7dec8a2 --- /dev/null +++ b/src/main/scala/scripts/ConsolidateOSMNodes.scala @@ -0,0 +1,101 @@ +package scripts + +import java.io.File +import scala.collection.mutable +import scala.xml.transform.{RewriteRule, RuleTransformer} +import scala.xml.{Elem, Node, PrettyPrinter, XML} + +case class LatLon(lat: Double, lon: Double) + +// Usage: +// ./gradlew :execute \ +// -PmaxRAM=10 \ +// -PmainClass=scripts.ConsolidateOSMNodes \ +// -PappArgs="['links0.osm','links_consolidated.osm']" +object ConsolidateOSMNodes { + private val locationToIds: mutable.Map[LatLon, mutable.Seq[Long]] = mutable.Map.empty.withDefaultValue(mutable.Seq.empty) + private val idToLocation: mutable.Map[Long, LatLon] = mutable.Map.empty + + private val replaceRedundantId = new RewriteRule { + override def transform(node: Node): Seq[Node] = { + node match { + case nd: Elem if nd.label == "nd" => + val id = (nd \ "@ref").text.toInt + val latLon = idToLocation(id) + val head :: tail = locationToIds(latLon).toList + if (tail.contains(id)) { + val metaData = scala.xml.Attribute(key = "ref", value = scala.xml.Text(head.toString), next = scala.xml.Null) + nd % metaData + } else nd + case n => n + } + } + } + + private val removeNode = new RewriteRule { + override def transform(node: Node): Seq[Node] = { + node match { + case node: Elem if node.label == "node" => + val id = (node \ "@id").text.toInt + val latLon = LatLon( + (node \ "@lat").text.toDouble, + (node \ "@lon").text.toDouble + ) + val _ :: tail = locationToIds(latLon).toList + if (tail.contains(id)) Seq.empty + else node + case n => n + } + } + } + + private def populateState(xml: Node): Unit = { + for { + osm <- xml \\ "osm" + node <- osm \\ "node" + } { + val id = (node \ "@id").text.toLong + val latLon = LatLon( + (node \ "@lat").text.toDouble, + (node \ "@lon").text.toDouble + ) + idToLocation.update(id, latLon) + val seq = locationToIds(latLon) + locationToIds.update(latLon, seq :+ id) + } + } + + def main(args: Array[String]): Unit = { + if (args.length != 2) { + println( + """ + |Usage: + |./gradlew :execute \ + | -PmaxRAM=10 \ + | -PmainClass=scripts.ConsolidateOSMNodes \ + | -PappArgs="['links0.osm','links_consolidated.osm']" + |""".stripMargin) + System.exit(1) + } + + val osmFile = new File(args(0)) + println("Loading xml..") + val xml = XML.loadFile(osmFile) + populateState(xml) + + val transformer = new RuleTransformer( + replaceRedundantId, + removeNode, + ) + + println("Consolidating network nodes..") + val output = { + val root = transformer.transform(xml) + val printer = new PrettyPrinter(120, 2, true) + XML.loadString(printer.format(root.head)) + } + + println("Writing xml..") + XML.save(args(1), output, "UTF-8", xmlDecl = true, null) + } +}