2024-04-20 14:32:01 +00:00
|
|
|
import 'package:anyhow/anyhow.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_map/flutter_map.dart';
|
|
|
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
2024-04-20 19:14:11 +00:00
|
|
|
import 'package:geojson_vi/geojson_vi.dart';
|
2024-04-20 14:32:01 +00:00
|
|
|
import 'package:latlong2/latlong.dart';
|
2024-04-20 22:35:16 +00:00
|
|
|
import 'package:uninav/util/geojson_util.dart';
|
|
|
|
import 'package:uninav/util/geomath.dart';
|
2024-04-20 14:32:01 +00:00
|
|
|
|
|
|
|
part 'model.freezed.dart';
|
|
|
|
|
|
|
|
@freezed
|
|
|
|
class Feature with _$Feature {
|
|
|
|
const Feature._();
|
|
|
|
|
|
|
|
const factory Feature({
|
|
|
|
required String name,
|
|
|
|
required FeatureType type,
|
|
|
|
String? description,
|
2024-04-20 19:14:11 +00:00
|
|
|
required GeoJSONGeometry geometry,
|
2024-04-20 14:32:01 +00:00
|
|
|
int? level,
|
2024-04-20 22:35:16 +00:00
|
|
|
String? building,
|
2024-04-21 08:47:29 +00:00
|
|
|
required String id,
|
2024-04-20 14:32:01 +00:00
|
|
|
}) = _Feature;
|
|
|
|
|
|
|
|
bool isPolygon() {
|
2024-04-20 19:14:11 +00:00
|
|
|
return geometry is GeoJSONPolygon;
|
2024-04-20 14:32:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isPoint() {
|
2024-04-20 19:14:11 +00:00
|
|
|
return geometry is GeoJSONPoint;
|
2024-04-20 14:32:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Result<Polygon> getPolygon({Polygon Function(List<LatLng>)? constructor}) {
|
|
|
|
if (isPolygon()) {
|
|
|
|
constructor ??= (pts) => Polygon(
|
2024-04-20 19:14:11 +00:00
|
|
|
points: pts,
|
|
|
|
borderColor: Colors.black26,
|
|
|
|
borderStrokeWidth: 2.0,
|
|
|
|
);
|
|
|
|
final polygon = geometry as GeoJSONPolygon;
|
2024-04-20 14:32:01 +00:00
|
|
|
// print(polygon.geometry!.geoSeries[0].geoPoints);
|
2024-04-20 19:14:11 +00:00
|
|
|
final points =
|
|
|
|
// polygon.coordinates[0].map((e) => LatLng(e[0], e[1])).toList();
|
2024-04-20 22:35:16 +00:00
|
|
|
polygon.coordinates[0].map(geoJSONToLatLon).toList();
|
2024-04-20 14:32:01 +00:00
|
|
|
|
|
|
|
// print(points);
|
|
|
|
return Ok(constructor(points));
|
|
|
|
} else {
|
|
|
|
return bail("Feature Geometry is not a Polygon");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Result<LatLng> getPoint() {
|
|
|
|
if (isPoint()) {
|
2024-04-20 19:14:11 +00:00
|
|
|
final point = geometry as GeoJSONPoint;
|
2024-04-20 22:35:16 +00:00
|
|
|
return Ok(geoJSONToLatLon(point.coordinates));
|
2024-04-20 14:32:01 +00:00
|
|
|
} else {
|
|
|
|
return bail("Feature Geometry is not a Point");
|
|
|
|
}
|
|
|
|
}
|
2024-04-20 22:35:16 +00:00
|
|
|
|
|
|
|
/// Checks if the current feature is on the specified layer.
|
|
|
|
///
|
|
|
|
/// For features that represent lifts or stairs, this method checks if the
|
|
|
|
/// feature's `connects_levels` list contains the specified layer.
|
|
|
|
///
|
|
|
|
/// For other feature types, this method simply checks if the feature's `level`
|
|
|
|
/// property matches the specified layer.
|
|
|
|
///
|
|
|
|
/// @param layer The layer to check for. **Layer can be `null`!**
|
|
|
|
/// `null` matches things such as Buildings without a layer.
|
|
|
|
/// @return `true` if the feature is on the specified layer, `false` otherwise.
|
|
|
|
bool isOnLevel(int? layer) {
|
|
|
|
if (type is Lift) {
|
|
|
|
return (type as Lift).connects_levels.contains(layer);
|
|
|
|
} else if (type is Stairs) {
|
|
|
|
return (type as Stairs).connects_levels.contains(layer);
|
|
|
|
}
|
|
|
|
return level == layer;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result<LatLng> getCenterPoint() {
|
|
|
|
if (isPolygon()) {
|
|
|
|
final polygon = geometry as GeoJSONPolygon;
|
|
|
|
final points = polygon.coordinates[0].map(geoJSONToLatLon).toList();
|
|
|
|
return Ok(polygonCenterMinmax(points));
|
|
|
|
} else if (isPoint()) {
|
|
|
|
final point = geometry as GeoJSONPoint;
|
|
|
|
return Ok(geoJSONToLatLon(point.coordinates));
|
|
|
|
} else {
|
|
|
|
return bail("Feature Geometry is not a Polygon or Point");
|
|
|
|
}
|
|
|
|
}
|
2024-04-20 14:32:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@freezed
|
|
|
|
class FeatureType with _$FeatureType {
|
|
|
|
// multiple feature types like lecture hall, toliet, ...
|
|
|
|
const factory FeatureType.building() = Building;
|
|
|
|
const factory FeatureType.lectureHall() = LectureHall;
|
2024-04-21 12:21:31 +00:00
|
|
|
const factory FeatureType.room(String roomNumber) = Room;
|
2024-04-20 14:32:01 +00:00
|
|
|
const factory FeatureType.door(List<String> connects) = Door;
|
|
|
|
const factory FeatureType.toilet(String toilet_type) = Toilet;
|
|
|
|
const factory FeatureType.stairs(List<int> connects_levels) = Stairs;
|
|
|
|
const factory FeatureType.lift(List<int> connects_levels) = Lift;
|
2024-04-21 12:21:31 +00:00
|
|
|
const factory FeatureType.foodDrink() = FoodDrink;
|
2024-04-20 14:32:01 +00:00
|
|
|
const factory FeatureType.publicTransport(
|
|
|
|
List<String> bus_lines, List<String> tram_lines) = PublicTransport;
|
2024-04-21 12:21:31 +00:00
|
|
|
const factory FeatureType.pcPool(String roomNumber) = PcPool;
|
2024-04-20 14:32:01 +00:00
|
|
|
}
|