mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
123 lines
No EOL
3.6 KiB
Swift
123 lines
No EOL
3.6 KiB
Swift
import Foundation
|
|
import MapKit
|
|
|
|
// MARK: - Configuration Models
|
|
|
|
struct GeoJSONOverlayConfiguration: Codable {
|
|
let version: String
|
|
let metadata: OverlayMetadata
|
|
let overlays: [OverlayDefinition]
|
|
}
|
|
|
|
struct OverlayMetadata: Codable {
|
|
let name: String
|
|
let description: String
|
|
let generated: String
|
|
}
|
|
|
|
struct OverlayDefinition: Codable {
|
|
let id: String
|
|
let name: String
|
|
let description: String
|
|
let rendering: RenderingProperties
|
|
let geojson: GeoJSONFeatureCollection
|
|
}
|
|
|
|
struct RenderingProperties: Codable {
|
|
let lineColor: String // Hex color (e.g., "#FF0000")
|
|
let lineOpacity: Double // 0.0 to 1.0
|
|
let lineThickness: Double // Line width in points
|
|
let fillOpacity: Double // 0.0 to 1.0
|
|
}
|
|
|
|
struct GeoJSONFeatureCollection: Codable {
|
|
let type: String // Always "FeatureCollection"
|
|
let features: [GeoJSONFeature]
|
|
}
|
|
|
|
struct GeoJSONFeature: Codable {
|
|
let type: String // Always "Feature"
|
|
let id: Int?
|
|
let geometry: GeoJSONGeometry
|
|
let properties: [String: AnyCodableValue]?
|
|
}
|
|
|
|
struct GeoJSONGeometry: Codable {
|
|
let type: String // "Point", "LineString", "Polygon", etc.
|
|
let coordinates: AnyCodableValue // Flexible coordinate structure
|
|
}
|
|
|
|
// MARK: - Flexible JSON Value Type
|
|
|
|
enum AnyCodableValue: Codable {
|
|
case string(String)
|
|
case int(Int)
|
|
case double(Double)
|
|
case bool(Bool)
|
|
case array([AnyCodableValue])
|
|
case object([String: AnyCodableValue])
|
|
case null
|
|
|
|
init(from decoder: Decoder) throws {
|
|
let container = try decoder.singleValueContainer()
|
|
|
|
if container.decodeNil() {
|
|
self = .null
|
|
} else if let value = try? container.decode(Bool.self) {
|
|
self = .bool(value)
|
|
} else if let value = try? container.decode(Int.self) {
|
|
self = .int(value)
|
|
} else if let value = try? container.decode(Double.self) {
|
|
self = .double(value)
|
|
} else if let value = try? container.decode(String.self) {
|
|
self = .string(value)
|
|
} else if let value = try? container.decode([AnyCodableValue].self) {
|
|
self = .array(value)
|
|
} else if let value = try? container.decode([String: AnyCodableValue].self) {
|
|
self = .object(value)
|
|
} else {
|
|
throw DecodingError.typeMismatch(AnyCodableValue.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unable to decode AnyCodableValue"))
|
|
}
|
|
}
|
|
|
|
func encode(to encoder: Encoder) throws {
|
|
var container = encoder.singleValueContainer()
|
|
|
|
switch self {
|
|
case .null:
|
|
try container.encodeNil()
|
|
case .bool(let value):
|
|
try container.encode(value)
|
|
case .int(let value):
|
|
try container.encode(value)
|
|
case .double(let value):
|
|
try container.encode(value)
|
|
case .string(let value):
|
|
try container.encode(value)
|
|
case .array(let value):
|
|
try container.encode(value)
|
|
case .object(let value):
|
|
try container.encode(value)
|
|
}
|
|
}
|
|
|
|
// Helper to convert coordinates to the format expected by MKGeoJSONDecoder
|
|
func toAnyObject() -> Any {
|
|
switch self {
|
|
case .null:
|
|
return NSNull()
|
|
case .bool(let value):
|
|
return value
|
|
case .int(let value):
|
|
return value
|
|
case .double(let value):
|
|
return value
|
|
case .string(let value):
|
|
return value
|
|
case .array(let values):
|
|
return values.map { $0.toAnyObject() }
|
|
case .object(let dict):
|
|
return dict.mapValues { $0.toAnyObject() }
|
|
}
|
|
}
|
|
} |