tdtp_parada_v2/tpmcqr_service/models/gtfs.py

100 lines
3.7 KiB
Python

from tpmcqr_service import db
from sqlalchemy.orm import aliased
from sqlalchemy import any_
from sqlalchemy import func
from geoalchemy2 import Geometry
from zoneinfo import ZoneInfo
class Lineas(db.Model):
__tablename__ = 'linea'
__table_args__ = { 'schema': 'public' }
id_linea = db.Column(db.String(150), primary_key=True )
id_operador = db.Column(db.String(150))
route_short_name = db.Column(db.String(150))
route_long_name = db.Column(db.String(150))
route_color = db.Column(db.String(150))
route_text_color = db.Column(db.String(150))
vigente = db.Column(db.Boolean)
class QRDev(db.Model):
__tablename__ = 'dispositivo'
__table_args__ = { 'schema': 'public' }
id_dispositivo = db.Column(db.String(100), primary_key=True )
id_paradero = db.Column(db.String(50))
class Paraderos(db.Model):
__tablename__ = 'paradero'
__table_args__ = { 'schema': 'public' }
id_paradero = db.Column(db.String(50), primary_key=True )
stop_name = db.Column(db.String(50))
stop_lat = db.Column(db.Float)
stop_lon = db.Column(db.Float)
class Shapes(db.Model):
__tablename__ = 'gtfs_shape'
__table_args__ = { 'schema': 'public' }
id_gtfs_pk = db.Column(db.Integer, primary_key=True )
id_shape = db.Column(db.String(150))
shape_pt_lat = db.Column(db.Float)
shape_pt_lon = db.Column(db.Float)
shape_pt_sequence = db.Column(db.Integer)
shape_dist_traveled = db.Column(db.Float)
class Trips(db.Model):
__tablename__ = 'gtfs_trips'
__table_args__ = { 'schema': 'public' }
id_trip = db.Column(db.String(150), primary_key=True)
id_linea = db.Column(db.String(150))
id_shape = db.Column(db.String(150))
service_id = db.Column(db.String(50))
class Stops(db.Model):
__tablename__ = 'gtfs_stop_times'
__table_args__ = { 'schema': 'public' }
id_paradero = db.Column(db.String(50), db.ForeignKey('public.paradero.id_paradero'), primary_key=True)
id_trip = db.Column(db.String(150), db.ForeignKey('public.gtfs_trips.id_trip'), primary_key=True)
def find_shape_position(shape_id, lat, lng):
Shape1 = aliased(Shapes)
Shape2 = aliased(Shapes)
point = func.ST_SetSRID(func.ST_MakePoint(lng, lat), 4326) # Create PostGIS point
segmento = db.session.query(
Shape1.shape_pt_sequence.label("start_sequence"),
# Shape2.shape_pt_sequence.label("end_sequence"),
Shape1.shape_dist_traveled.label("traveled_start"),
Shape2.shape_dist_traveled.label("traveled_end"),
func.ST_Distance(
func.ST_MakeLine(
func.ST_SetSRID(func.ST_MakePoint(Shape1.shape_pt_lon, Shape1.shape_pt_lat), 4326),
func.ST_SetSRID(func.ST_MakePoint(Shape2.shape_pt_lon, Shape2.shape_pt_lat), 4326)
),
point
).label("distance"),
func.ST_LineLocatePoint( # Compute fractional position on the segment
func.ST_MakeLine(
func.ST_SetSRID(func.ST_MakePoint(Shape1.shape_pt_lon, Shape1.shape_pt_lat), 4326),
func.ST_SetSRID(func.ST_MakePoint(Shape2.shape_pt_lon, Shape2.shape_pt_lat), 4326)
),
point
).label("fraction")
).filter(
Shape1.id_shape == shape_id,
Shape2.id_shape == shape_id,
Shape2.shape_pt_sequence == Shape1.shape_pt_sequence + 1 # Ensure correct segment order
).order_by("distance").first()
avanzado = segmento.traveled_start + segmento.fraction * (segmento.traveled_end - segmento.traveled_start)
return ( segmento.start_sequence, avanzado )