92 lines
3.3 KiB
Python
92 lines
3.3 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__ = 'device'
|
|
__table_args__ = { 'schema': 'public' }
|
|
|
|
id_dispositivo = db.Column(db.String(100), primary_key=True )
|
|
id_paradero = db.Column(db.String(50))
|
|
|
|
class Paradero(db.Model):
|
|
__tablename__ = 'paredero'
|
|
__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(Base):
|
|
__tablename__ = 'gtfs_trips'
|
|
__table_args__ = { 'schema': 'public' }
|
|
|
|
id_trip = Column(String(150), primary_key=True)
|
|
id_linea = Column(String(150))
|
|
id_shape = Column(String(150))
|
|
service_id = Column(String(50))
|
|
|
|
|
|
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.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 )
|