Στη συνέχεια παρατίθενται ορισµένα συµπληρωµατικά στοιχεία σχετικά µε την προσοµοίωση της τροχιάς κινούµενων αντικειµένων, όπως υλοποιήθηκε σε περιβάλλον Oracle Spatial 8i DBMS. i. ηµιουργία της δοµής των πινάκων και των ευρετηρίων τους στη β. δ. CREATE TABLE mpoints (vid NUMBER(5) NOT NULL, type VARCHAR2(20), t NUMBER(5), pos MDSYS.SDO_GEOMETRY, flag NUMBER(1), PRIMARY KEY (vid,t)); CREATE INDEX mpointstime_idx ON mpoints(t); CREATE TABLE zones (zone_id number(5) PRIMARY KEY, name varchar2(30), sector MDSYS.SDO_GEOMETRY); CREATE TABLE locations (name VARCHAR2(50) PRIMARY KEY, pos MDSYS.SDO_GEOMETRY); ii. Ορισµός των χωρικών ευρετηρίων και της ανοχής (0.001) INSERT INTO USER_SDO_GEOM_METADATA VALUES('mpoints','pos', CREATE INDEX mpoints_idx ON mpoints(pos) INSERT INTO USER_SDO_GEOM_METADATA VALUES('zones','sector', CREATE INDEX zones_idx ON zones(sector) INSERT INTO USER_SDO_GEOM_METADATA VALUES('locations','pos', CREATE INDEX locations_idx ON locations(pos) 207
Συστήµατα ρευµάτων δεδοµένων για κινούµενα αντικείµενα. iii. Μερικά επιπρόσθετα παραδείγµατα ερωτηµάτων Q1: Προσδιορισµός µέσης ταχύτητας κίνησης ανά όχηµα εντός των τελευταίων 10 λεπτών --Η ORACLE 8i δεν υποστηρίζει συναθροιστικά παράθυρα (window aggregates) σε --χωρικά αντικείµενα! Γι αυτό και η ακόλουθη όψη (view) δεν λειτουργεί: CREATE OR REPLACE VIEW V_Delta_Distances AS SELECT vid, t, SDO_GEOM.SDO_DISTANCE(FIRST_VALUE(pos) OVER (PARTITION BY vid ROWS 1 PRECEDING), LAST_VALUE(pos) OVER (PARTITION BY vid ROWS 1 PRECEDING), 0.001) AS Delta_Distance FROM mpoints V, Zones Z WHERE SDO_RELATE(V.pos, Z.sector, 'mask=inside querytype=window') = 'TRUE' AND Z.name=' ΑΚΤΥΛΙΟΣ' GROUP BY vid, t, pos; --Έτσι, υιοθετείται η παρακάτω λύση, χωρίς χρήση παραθύρων: CREATE OR REPLACE VIEW V_Delta_Distances AS SELECT V1.vID, V1.t, SDO_GEOM.SDO_DISTANCE(V1.pos,V2.pos,0.001) AS Delta_Distance FROM mpoints V1, mpoints V2, Zones Z WHERE SDO_RELATE(V1.pos, Z.sector, 'mask=inside querytype=window') = 'TRUE' AND SDO_RELATE(V2.pos, Z.sector, 'mask=inside querytype=window') = 'TRUE' AND Z.name=' ΑΚΤΥΛΙΟΣ' AND V1.vID=V2.vID AND V1.t=V2.t+1; CREATE OR REPLACE VIEW V_Delta_Averages AS SELECT route, t, COUNT(*) OVER (PARTITION BY route RANGE 599 PRECEDING) AS DT, SUM(delta_distance) OVER (PARTITION BY route RANGE 599 PRECEDING) AS DS FROM V_Delta_Distances GROUP BY delta_distance,route,t; --Το τελικό αποτέλεσµα για τη µέση ταχύτητα του δεκαλέπτου: SELECT route, t, (DS/DT) AS Avg_speed FROM V_Delta_Averages; Q2: Πολυσύχναστα σηµεία διέλευσης πολλαπλών τροχιών SELECT L.name, P.t, COUNT(*) OVER (PARTITION BY P.vID ORDER BY P.t ROWS CURRENT ROW) AS cnt FROM locations L, mpoints P WHERE t BETWEEN 1000 AND 1005 AND L.name IN ('ΑΚΡΟΠΟΛΗ', 'ΜΕΤΑΞΟΥΡΓΕΙΟ','ΦΙΞ','ΚΥΨΕΛΗ','ΨΥΧΙΚΟ') AND SDO_WITHIN_DISTANCE(P.pos,L.pos,'distance=200') = 'TRUE' GROUP BY L.name,P.vID,P.t HAVING COUNT(*)>0; 208
Q3: Ερώτηµα εγγύτητας µε κατώφλι --Για κάθε όχηµα προσδιόρισε το πλήθος των πλησιέστερων οχηµάτων (λ.χ. σε --απόσταση µέχρι 300m), αλλά µόνο όταν ένα τουλάχιστον απ αυτά απέχει λιγότερο --από 100m (πολύ αργή εκτέλεση, ακόµη και µετά την επιλογή λίγων τροχιών). --Προφανώς, φταίει το διπλό GROUP BY (αναπόφευκτο, λόγω της δοµής --των παραθύρων στην Oracle 8i). SELECT vid, t, SUM(cnt) FROM (SELECT V1.vID, V1.t, COUNT(V2.vID) AS cnt FROM mpoints V1, mpoints V2 WHERE V1.vID IN (554, 392, 303, 2, 595) AND V1.vID<>V2.vID AND V1.t=V2.t AND SDO_WITHIN_DISTANCE(V1.pos,V2.pos,'distance=300') = 'TRUE' GROUP BY V1.vID, V1.t HAVING MIN(SDO_GEOM.SDO_DISTANCE(V1.pos,V2.pos,0.001))<100) GROUP BY vid,t; iv. Απόπειρα εισαγωγή χωροχρονικού οροσήµου ως σύνθετου τύπου δεδοµένων --Ο νέος τύπος δεδοµένων (το TIMESTAMP δεν υποστηρίζεται στην Oracle 8i) CREATE OR REPLACE TYPE spacetimestamp AS OBJECT (pos MDSYS.SDO_GEOMETRY, t INTEGER) --Αλλαγή της δοµής του πίνακα και συµπλήρωση του νέου πεδίου µε τιµές ALTER TABLE mpoints ADD (spacetime_ref spacetimestamp); UPDATE mpoints SET spacetime_ref=spacetimestamp(pos,t); --Όµως η Oracle 8i δεν µπορεί να δηµιουργήσει το παρακάτω χωρικό ευρετήριο --για τον νέο τύπο δεδοµένων CREATE INDEX mpoints_space_time_idx ON mpoints(spacetime_ref.pos) v. Περιληπτικές δοµές (υλοποιηµένες όψεις και triggers) --Χορήγηση ειδικών προνοµίων για τον ορισµό υλοποιηµένων όψεων GRANT CREATE ANY MATERIALIZED VIEW, ALTER ANY MATERIALIZED VIEW, DROP ANY MATERIALIZED VIEW, QUERY REWRITE, GLOBAL QUERY REWRITE TO kostas WITH ADMIN OPTION; --Ορισµός υλοποιηµένης όψης για τον πίνακα mpoints CREATE MATERIALIZED VIEW LOG ON mpoints WITH ROWID INCLUDING NEW VALUES; 209
Συστήµατα ρευµάτων δεδοµένων για κινούµενα αντικείµενα. --Όµως η απόπειρα ορισµού περιληπτικής δοµής µε χωροχρονική αναφορά αποτυγχάνει --(Μήνυµα σφάλµατος: object data types are not supported in this context) CREATE MATERIALIZED VIEW mv_mpoints REFRESH FAST ON COMMIT AS SELECT mp.vid, mp.pos, mp.t FROM mpoints mp WHERE MOD(mp.t,100)=0; --Triggers (αλλά πολύ αργή εκτέλεση...) CREATE TABLE mpoints_sketch (vid NUMBER(5) NOT NULL, t NUMBER(5), pos MDSYS.SDO_GEOMETRY, PRIMARY KEY (vid,t)); INSERT INTO USER_SDO_GEOM_METADATA VALUES('mpoints_sketch','pos', CREATE INDEX mpoints_sketch_idx ON mpoints_sketch(pos) CREATE OR REPLACE TRIGGER tr_mpoints AFTER INSERT OR UPDATE OF t ON mpoints FOR EACH ROW WHEN (MOD(NEW.t,100)=0) BEGIN INSERT INTO mpoints_sketch VALUES (:NEW.vID, :NEW.t, :NEW.pos); END; vi. ιερεύνηση οµοιότητας τροχιών --Προσπάθεια (περίπλοκη και πολύ χρονοβόρα...) εντοπισµού οµοιότητας µεταξύ --τροχιών οµάδας αντικειµένων (701, 764, 617, 904, 58, 93). Για το ερώτηµα --επιλέγεται το 904 ώστε να βρεθούν οι τροχιές που µοιάζουν µε τη δική του. --Καταρχάς, οι τροχιές πρέπει να αναπαρασταθούν από ευθύγραµµα τµήµατα... CREATE TABLE trajectories_sketch (vid NUMBER(5) NOT NULL, from_time NUMBER(5) NOT NULL, to_time NUMBER(5) NOT NULL, route MDSYS.SDO_GEOMETRY); INSERT INTO USER_SDO_GEOM_METADATA VALUES('trajectories_sketch','route', CREATE INDEX trajectories_idx ON trajectories_sketch(route) 210
--Στον πίνακα trajectories_sketch εισάγονται προσεγγίσεις των τροχιών, --µε ρυθµό δειγµατοληψίας 1 σηµείο κάθε 60 δευτερόλεπτα (για κάθε τροχιά). DECLARE CURSOR c1 is SELECT m1.vid, m1.pos, m2.pos, m1.t, m2.t FROM mpoints m1, mpoints m2 WHERE m1.vid=m2.vid AND mod(m1.t,60)=0 AND m1.t=m2.t+60; my_route mpoints.vid%type; my_pos mpoints.pos%type; my_t mpoints.t%type; prev_pos mpoints.pos%type; prev_t mpoints.t%type; BEGIN DELETE FROM trajectories_sketch; OPEN c1; LOOP FETCH c1 INTO my_route, my_pos, prev_pos, my_t, prev_t; EXIT WHEN c1%notfound; INSERT INTO trajectories_sketch VALUES (my_route,prev_t,my_t,mdsys.sdo_geometry(2002,null,null, MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1), MDSYS.SDO_ORDINATE_ARRAY(prev_pos.SDO_POINT.x,prev_pos.SDO_POINT.y, my_pos.sdo_point.x,my_pos.sdo_point.y))); IF (MOD(c1%ROWCOUNT,200)=0) THEN END IF; END LOOP; CLOSE c1; END; / --Όµως, όταν το αντικείµενο ακινητεί δεν υπάρχει στην πραγµατικότητα γραµµή... --γι αυτό και οι σχετικές εγγραφές πρέπει να διαγραφούν... SELECT vid,from_time,to_time FROM trajectories_sketch WHERE SDO_GEOM.SDO_LENGTH(route,0.001)=0; DELETE FROM trajectories_sketch WHERE SDO_GEOM.SDO_LENGTH(route,0.001)=0; --Η απόσταση όλων των ζευγών πρέπει να υπολογιστεί, αλλά απαλείφοντας τα ζεύγη --που απέχουν πάνω από 300m. Το παρακάτω απλό ερώτηµα τρέχει ΠΟΛΥ ΑΡΓΑ... SELECT V1.vID, V2.vID, V1.to_time AS t1, V2.to_time AS t2, SDO_GEOM.SDO_DISTANCE(V1.route,V2.route,0.001) AS dist FROM trajectories_sketch V1, trajectories_sketch V2 WHERE V1.vID<>V2.vID AND V1.vID=904 AND V1.to_time BETWEEN 1000 AND 1500 AND SDO_WITHIN_DISTANCE(V1.route,V2.route,'distance=300') = 'TRUE'; 211
Συστήµατα ρευµάτων δεδοµένων για κινούµενα αντικείµενα. --Γι αυτό και δηµιουργείται πίνακας... CREATE TABLE trajectory_distances (P1 NUMBER(5) NOT NULL, P2 NUMBER(5) NOT NULL, T1 NUMBER(5) NOT NULL, T2 NUMBER(5) NOT NULL, DIST NUMBER(8,2)); CREATE INDEX traj_p1_idx ON trajectory_distances(p1); CREATE INDEX traj_p2_idx ON trajectory_distances(p2); CREATE INDEX traj_t1_idx ON trajectory_distances(t1); CREATE INDEX traj_t2_idx ON trajectory_distances(t2); --... ο οποίος συµπληρώνεται µε εγγραφές βάσει του παρακάτω κώδικα PL/SQL DECLARE CURSOR c1 is SELECT vid, to_time, route FROM trajectories_sketch WHERE to_time>1000; my_p1 trajectories_sketch.vid%type; my_t1 trajectories_sketch.to_time%type; my_route trajectories_sketch.route%type; BEGIN OPEN c1; LOOP FETCH c1 INTO my_p1, my_t1, my_route; EXIT WHEN c1%notfound; INSERT INTO trajectory_distances SELECT my_p1, V1.vID, my_t1, V1.to_time, SDO_GEOM.SDO_DISTANCE(V1.route,my_route,0.001) FROM trajectories_sketch V1 WHERE V1.vID<>my_p1 AND SDO_WITHIN_DISTANCE(V1.route,my_route,'distance=300')='TRUE'; IF (MOD(c1%ROWCOUNT,100)=0) THEN END IF; END LOOP; CLOSE c1; END; / --Τα ζεύγη όπου συµµετέχει το 904 για ένα χρονικό διάστηµα αποµονώνονται... CREATE OR REPLACE VIEW v_traj904 AS SELECT DISTINCT p2, t2 FROM trajectory_distances WHERE p1=904 AND t1 BETWEEN 900 AND 1500; --Εντοπίζονται οι σχετικές συστάδες τροχιών... CREATE OR REPLACE VIEW v_clusters AS SELECT DISTINCT V1.p2, V1.t2 AS START_TIME, V2.t2 AS END_TIME FROM v_traj904 V1, v_traj904 V2 WHERE V1.p2=V2.p2 212
AND V1.t2<V2.t2 AND NOT EXISTS (SELECT V3.t2 FROM v_traj904 V3 WHERE V3.p2=V1.p2 AND V3.t2=V1.t2-60) AND NOT EXISTS (SELECT V4.t2 FROM v_traj904 V4 WHERE V4.p2=V2.p2 AND V4.t2=V2.t2+60); --Και επιστρέφονται µόνο οι εγγραφές που αφορούν --τα µεγαλύτερα κοινά συνεχόµενα υποτµήµατα SELECT * FROM v_clusters C1 WHERE (((C1.END_TIME-C1.START_TIME)/60)+1)= (SELECT COUNT(*) FROM v_traj904 C2 WHERE C2.p2=C1.p2 AND C2.t2 BETWEEN C1.START_TIME AND C1.END_TIME) ORDER BY C1.p2, C1.START_TIME, C1.END_TIME; Σχέδιο???.1: Χαρτογραφική αναπαράσταση µιας οµάδας τροχιών των οποίων η οµοιότητα διερευνήθηκε σε περιβάλλον Oracle Spatial 8i DBMS. 213