File : routeProviders/PublicTransportHolesRemover.js

1
/*
2
Copyright - 2017 2023 - wwwouaiebe - Contact: https://www.ouaie.be/
3
4
This  program is free software;
5
you can redistribute it and/or modify it under the terms of the
6
GNU General Public License as published by the Free Software Foundation;
7
either version 3 of the License, or any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
*/
18
/*
19
Changes:
20
    - v4.0.0:
21
        - created from v3.6.0
22
Doc reviewed 202208
23
 */
24
25
import theSphericalTrigonometry from '../core/lib/SphericalTrigonometry.js';
26
27
import { ZERO, ONE, TWO, THREE } from '../main/Constants.js';
28
29
/* ------------------------------------------------------------------------------------------------------------------------- */
30
/**
31
coming soon...
32
@ignore
33
*/
34
/* ------------------------------------------------------------------------------------------------------------------------- */
35
36
class PublicTransportHolesRemover {
37
38
    #publicTransportData;
39
40
    #computeDistances ( node1, node2, distancesBetweenWays ) {
41
        if ( node1.isNode3Ways || node2.isNode3Ways ) {
42
            return;
43
        }
44
        distancesBetweenWays.push (
45
            {
46
                distance : theSphericalTrigonometry.pointsDistance ( [ node1.lat, node1.lon ], [ node2.lat, node2.lon ] ),
47
                nodesId : [ node1.id, node2.id ]
48
            }
49
        );
50
    }
51
52
    /**
53
    */
54
55
    #removeHoles ( ) {
56
57
        // for every start node or end node of each way we compute the distance
58
        // to the start node and end node of all others ways
59
60
        const distancesBetweenWays = [];
61
        const waysArray = Array.from ( this.#publicTransportData.waysMap.values ( ) );
62
        let loopCounter = ONE;
63
64
        waysArray.forEach (
65
            way => {
66
                for ( let wayCounter = loopCounter; wayCounter < waysArray.length; wayCounter ++ ) {
67
                    const nodesIds = [];
68
                    nodesIds.push ( this.#publicTransportData.nodesMap.get (
69
                        this.#publicTransportData.firstOf ( way.nodesIds ) )
70
                    );
71
                    nodesIds.push ( this.#publicTransportData.nodesMap.get (
72
                        this.#publicTransportData.lastOf ( way.nodesIds ) )
73
                    );
74
                    nodesIds.push ( this.#publicTransportData.nodesMap.get (
75
                        this.#publicTransportData.firstOf ( waysArray [ wayCounter ].nodesIds ) )
76
                    );
77
                    nodesIds.push ( this.#publicTransportData.nodesMap.get (
78
                        this.#publicTransportData.lastOf ( waysArray [ wayCounter ].nodesIds ) )
79
                    );
80
81
                    this.#computeDistances ( nodesIds [ ZERO ], nodesIds [ TWO ], distancesBetweenWays );
82
                    this.#computeDistances ( nodesIds [ ZERO ], nodesIds [ THREE ], distancesBetweenWays );
83
                    this.#computeDistances ( nodesIds [ ONE ], nodesIds [ TWO ], distancesBetweenWays );
84
                    this.#computeDistances ( nodesIds [ ONE ], nodesIds [ THREE ], distancesBetweenWays );
85
                }
86
                loopCounter ++;
87
            }
88
        );
89
90
        // the shortest distance is searched
91
        let minDistance = distancesBetweenWays [ ZERO ];
92
        distancesBetweenWays.forEach (
93
            distanceBetwwenWays => {
94
                if ( distanceBetwwenWays.distance < minDistance.distance ) {
95
                    minDistance = distanceBetwwenWays;
96
                }
97
            }
98
        );
99
100
        // a new way is created and added to the way map, using the shortest distance
101
        const newWay = {
102
            id : this.#publicTransportData.newId,
103
            type : 'way',
104
            nodesIds : minDistance.nodesId,
105
            distance : minDistance.distance
106
        };
107
        this.#publicTransportData.waysMap.set ( newWay.id, newWay );
108
109
        // start and end node are is adapted
110
        const startNode = this.#publicTransportData.nodesMap.get ( minDistance.nodesId [ ZERO ] );
111
        const wayIdAtStart = startNode.startingWaysIds.concat ( startNode.endingWaysIds ) [ ZERO ];
112
        startNode.startingWaysIds.push ( newWay.id );
113
        const endNode = this.#publicTransportData.nodesMap.get ( minDistance.nodesId [ ONE ] );
114
        const wayIdAtEnd = endNode.startingWaysIds.concat ( endNode.endingWaysIds ) [ ZERO ];
115
        endNode.endingWaysIds.push ( newWay.id );
116
117
        // and the two ways merged with the new one
118
        this.#publicTransportData.mergeWays ( this.#publicTransportData.mergeWays ( newWay.id, wayIdAtStart ), wayIdAtEnd );
119
120
        // and we restart recursively till all the possible ways are joined
121
        if ( this.#publicTransportData.waysMap.size > ( ( this.#publicTransportData.nodes3WaysCounter * TWO ) + ONE ) ) {
122
            this.#removeHoles ( );
123
        }
124
    }
125
126
    /**
127
    The constructor
128
    */
129
130
    constructor ( publicTransportData ) {
131
        Object.freeze ( this );
132
        this.#publicTransportData = publicTransportData;
133
    }
134
135
    removeHoles ( ) {
136
        this.#removeHoles ( );
137
    }
138
}
139
140
export default PublicTransportHolesRemover;
141
142
/* --- End of file --------------------------------------------------------------------------------------------------------- */
143