Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 61 additions & 27 deletions src/Shared/EditorLayer/EditorMapLayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,47 @@ final class EditorMapLayer: CALayer {
})
}


private static let oneWayArrowChevronLength: Double = 15
private static let oneWayArrowChevronWidth: Double = 5
/// Along-way distance from motor chevron tip to bicycle chevron tip (motor icon + gap + bicycle icon).
private static let bicycleContraflowArrowLongitudinalOffset: Double = 3 * oneWayArrowChevronLength

private func makeOneWayArrowLayer(
at loc: OSMPoint,
direction dir: OSMPoint,
chevronLength len: Double,
alongWayOffset: Double,
fillColor: UIColor,
zPosition: CGFloat
) -> CAShapeLayerWithProperties {
let position = OSMPoint(x: loc.x + dir.x * alongWayOffset,
y: loc.y + dir.y * alongWayOffset)
let width = Self.oneWayArrowChevronWidth

let p1 = OSMPoint(x: position.x - dir.x * len + dir.y * width,
y: position.y - dir.y * len - dir.x * width)
let p2 = OSMPoint(x: position.x - dir.x * len - dir.y * width,
y: position.y - dir.y * len + dir.x * width)

let arrowPath = CGMutablePath()
arrowPath.move(to: CGPoint(x: p1.x, y: p1.y))
arrowPath.addLine(to: CGPoint(x: position.x, y: position.y))
arrowPath.addLine(to: CGPoint(x: p2.x, y: p2.y))
arrowPath
.addLine(to: CGPoint(x: CGFloat(position.x - dir.x * len * 0.5),
y: CGFloat(position.y - dir.y * len * 0.5)))
arrowPath.closeSubpath()

let arrow = CAShapeLayerWithProperties()
arrow.path = arrowPath
arrow.fillColor = fillColor.cgColor
arrow.strokeColor = UIColor.white.cgColor
arrow.lineWidth = 0.5
arrow.zPosition = zPosition
return arrow
}

// clip a way to the path inside the viewable rect so we can draw a name on it
func pathClipped(toViewRect way: OsmWay, length pLength: UnsafeMutablePointer<CGFloat>?) -> CGPath? {
var path: CGMutablePath?
Expand Down Expand Up @@ -1409,36 +1450,29 @@ final class EditorMapLayer: CALayer {
}
let isHighlight = highlights.contains(way)
if way.isOneWay != .NONE || isHighlight {
let showBicycleContraflow = way.allowsBicycleContraflow()
let arrowZ = isHighlight ? self.Z_HIGHLIGHT_ARROW : self.Z_ARROW
// arrow heads
invoke(alongScreenClippedWay: way, offset: 50, interval: 100, block: { loc, dir in
// draw direction arrow at loc/dir
let reversed = way.isOneWay == ONEWAY.BACKWARD
let len: Double = reversed ? -15 : 15
let width: Double = 5

let p1 = OSMPoint(x: loc.x - dir.x * len + dir.y * width,
y: loc.y - dir.y * len - dir.x * width)
let p2 = OSMPoint(x: loc.x - dir.x * len - dir.y * width,
y: loc.y - dir.y * len + dir.x * width)

let arrowPath = CGMutablePath()
arrowPath.move(to: CGPoint(x: p1.x, y: p1.y))
arrowPath.addLine(to: CGPoint(x: loc.x, y: loc.y))
arrowPath.addLine(to: CGPoint(x: p2.x, y: p2.y))
arrowPath
.addLine(to: CGPoint(x: CGFloat(loc.x - dir.x * len * 0.5),
y: CGFloat(loc.y - dir.y * len * 0.5)))
arrowPath.closeSubpath()

let arrow = CAShapeLayerWithProperties()
arrow.path = arrowPath
arrow.lineWidth = 1
arrow.fillColor = UIColor.black.cgColor
arrow.strokeColor = UIColor.white.cgColor
arrow.lineWidth = 0.5
arrow.zPosition = isHighlight ? self.Z_HIGHLIGHT_ARROW : self.Z_ARROW

layers.append(arrow)
let motorLen = reversed ? -Self.oneWayArrowChevronLength : Self.oneWayArrowChevronLength
let behindAlongWay = motorLen > 0
? -Self.bicycleContraflowArrowLongitudinalOffset
: Self.bicycleContraflowArrowLongitudinalOffset
if showBicycleContraflow {
layers.append(self.makeOneWayArrowLayer(at: loc,
direction: dir,
chevronLength: -motorLen,
alongWayOffset: behindAlongWay,
fillColor: .systemBlue,
zPosition: arrowZ))
}
layers.append(self.makeOneWayArrowLayer(at: loc,
direction: dir,
chevronLength: motorLen,
alongWayOffset: 0,
fillColor: .black,
zPosition: arrowZ))
})
}

Expand Down
9 changes: 9 additions & 0 deletions src/Shared/OSMModels/OsmWay.swift
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,15 @@ final class OsmWay: OsmBaseObject, NSSecureCoding {
return _isOneWay!
}

// https://wiki.openstreetmap.org/wiki/Key:oneway:bicycle
/// True when the way is one-way for general traffic but cyclists may use the opposite direction.
func allowsBicycleContraflow() -> Bool {
guard isOneWay != .NONE else {
return false
}
return tags["oneway:bicycle"] == "no"
}

// return the point on the way closest to the supplied point
override func latLonOnObject(forLatLon target: LatLon) -> LatLon {
switch nodes.count {
Expand Down
Loading