source: subversion/applications/editors/potlatch/way.as @ 12005

Last change on this file since 12005 was 11933, checked in by richard, 11 years ago

finished Rails-friendly amf_controller. Note that this requires Tom's patched composite_primary_keys to work unless you tell Potlatch to use SQL reads

File size: 40.8 KB
Line 
1
2        // =====================================================================================
3        // OOP classes - OSMWay
4
5        // ---- Initialise
6       
7        function OSMWay() {
8                this.resetBBox();
9                this.path=new Array();                  // list of nodes
10                this.attr=new Array();                  // hash of tags
11                this.mergedways=new Array();    // list of ways merged into this
12        };
13
14        OSMWay.prototype=new MovieClip();
15        OSMWay.prototype.clean=true;                            // altered since last upload?
16        OSMWay.prototype.uploading=false;                       // currently uploading?
17        OSMWay.prototype.locked=false;                          // locked against upload?
18        OSMWay.prototype.version=0;                                     // version number?
19        OSMWay.prototype.historic=false;                        // is this an undeleted, not-uploaded way?
20        OSMWay.prototype.checkconnections=false;        // check shared nodes on reload
21
22        // ---- Load from remote server
23
24        OSMWay.prototype.load=function() {
25                responder = function() { };
26                responder.onResult = function(result) {
27                        _root.waysreceived+=1;
28                        var w=result[0];
29                        if (length(result[1])==0) { removeMovieClip(_root.map.ways[w]); 
30                                                                                removeMovieClip(_root.map.areas[w]); return; }
31                        var i,id,x,y,prepoint;
32                        _root.map.ways[w].clean=true;
33                        _root.map.ways[w].locked=false;
34                        _root.map.ways[w].historic=false;
35                        _root.map.ways[w].version=result[3];
36                        _root.map.ways[w].removeNodeIndex();
37                        _root.map.ways[w].path=[];
38                        _root.map.ways[w].resetBBox();
39                        for (i=0; i<result[1].length; i++) {
40                                x =result[1][i][0];
41                                y =result[1][i][1];
42                                id=result[1][i][2];
43                                _root.map.ways[w].updateBBox(x,y);
44                                x=long2coord(x); y=lat2coord(y);
45                                if (nodes[id]) {
46                                        // already exists: move node in other ways if required
47                                        // ** maybe we should take out 'w'? not sure
48                                        if (_root.map.ways[w].checkconnections) { nodes[id].moveTo(x,y,w); }
49                                } else {
50                                        // doesn't exist, so create new node
51                                        _root.nodes[id]=new Node(id,x,y,result[1][i][3]);
52                                        if (id==prenode) { prepoint=i; }
53                                }
54                                _root.map.ways[w].path.push(_root.nodes[id]);
55                                _root.nodes[id].addWay(w);
56                        }
57                        _root.map.ways[w].attr=result[2];
58                        _root.map.ways[w].redraw();
59                        if (w==preway) { _root.map.ways[w].select(); preway=undefined; }
60                        if (prepoint)  { _root.map.ways[w].select(); 
61                                                         _root.map.anchors[prepoint].select();
62                                                         prenode=prepoint=undefined; }
63                        _root.map.ways[w].clearPOIs();
64                        _root.map.ways[w].checkconnections=false;
65                };
66                remote_read.call('getway',responder,Math.floor(this._name));
67        };
68
69        OSMWay.prototype.loadFromDeleted=function(version) {
70                delresponder=function() { };
71                delresponder.onResult=function(result) {
72                        var code=result.shift(); if (code) { handleError(code,result); return; }
73                        var i,id;
74                        var w=result[0];
75                        // Don't mark as unclean if it's actually visible
76                        if (result[4]) { _root.map.ways[w].historic=false; _root.map.ways[w].clean=true;  }
77                                  else { _root.map.ways[w].historic=true;  _root.map.ways[w].clean=false; }
78                        _root.map.ways[w].version=result[3];
79                        _root.map.ways[w].removeNodeIndex();
80                        _root.map.ways[w].path=[];
81                        _root.map.ways[w].resetBBox();
82                        for (i=0; i<result[1].length; i++) {
83                                x =result[1][i][0];
84                                y =result[1][i][1];
85                                id=result[1][i][2]; if (id<0) { id=--_root.newnodeid; } // assign negative IDs to anything moved
86                                _root.map.ways[w].updateBBox(x,y);
87                                x=long2coord(x); y=lat2coord(y);
88                                if (nodes[id]) {
89                                        nodes[id].moveTo(x,y,w);
90                                } else {
91                                        _root.nodes[id]=new Node(id,x,y,result[1][i][4]);
92                                }
93                                _root.map.ways[w].path.push(_root.nodes[id]);
94                                _root.nodes[id].addWay(w);
95                        }
96                        _root.map.ways[w].attr=result[2];
97                        if (w==wayselected) { _root.map.ways[w].select(); }
98                                                   else { _root.map.ways[w].locked=true; }
99                        _root.map.ways[w].redraw();
100                        _root.map.ways[w].clearPOIs();
101                };
102                remote_read.call('getway_old',delresponder,Math.floor(this._name),Math.floor(version));
103        };
104
105        OSMWay.prototype.clearPOIs=function() {
106                // check if any way nodes are POIs, delete the POIs if so
107                var i,z;
108                z=this.path;
109                for (i in z) {
110                        if (_root.map.pois[this.path[i].id]) { removeMovieClip(_root.map.pois[this.path[i].id]); }
111                }
112        };
113
114        // ---- Draw line
115
116        OSMWay.prototype.redraw=function(skip) {
117                this.createEmptyMovieClip("taggednodes",2);
118
119                if (skip) {
120                        // We're at the same scale as previously, so don't redraw
121                        // ** will refactor this when we do proper POI icons
122                        for (var i=1; i<this.path.length; i+=1) {
123                                if (this.path[i].tagged) {
124                                        this.taggednodes.attachMovie("poiinway",i,i);
125                                        this.taggednodes[i]._x=this.path[i].x;
126                                        this.taggednodes[i]._y=this.path[i].y;
127                                        this.taggednodes[i]._xscale=this.taggednodes[i]._yscale=taggedscale;
128                                }
129                        }
130                } else {
131
132                        // Either the line has changed, or we've changed scale
133                        this.createEmptyMovieClip("line",1);                                    // clear line
134                        var linealpha=100; // -50*(this.locked==true);
135                        var casingx=1.5; var casingcol=0;
136       
137                        // Set stroke
138       
139                        if              (this.locked)                                    { this.line.lineStyle(linewidth,0xFF0000,linealpha,false,"none"); }
140                        else if (colours[this.attr["highway"]])  { this.line.lineStyle(linewidth,colours[this.attr["highway" ]],linealpha,false,"none"); }
141                        else if (colours[this.attr["waterway"]]) { this.line.lineStyle(linewidth,colours[this.attr["waterway"]],linealpha,false,"none"); }
142                        else if (colours[this.attr["railway"]])  { this.line.lineStyle(linewidth,colours[this.attr["railway" ]],linealpha,false,"none"); }
143                        else {
144                                var c=0xAAAAAA; var z=this.attr;
145                                for (var i in z) { if (i!='created_by' && this.attr[i]!='' && this.attr[i].substr(0,6)!='(type ') { c=0x707070; } }
146                                this.line.lineStyle(linewidth,c,linealpha,false,"none");
147                        }
148                       
149                        // Draw fill/casing
150       
151                        var f=this.getFill();
152                        if (preferences.data.noname && this.attr["highway"] && (!this.attr["name"] || this.attr["name"].substr(0,6)=='(type ')) {
153                                casingx=2; casingcol=0xFF0000;
154                        } else if (this.attr["bridge"] && this.attr["bridge"]!="no") { casingx=2; }
155       
156                        if ((f>-1 || casing[this.attr['highway']]) && !this.locked) {
157                                if (!_root.map.areas[this._name]) { _root.map.areas.createEmptyMovieClip(this._name,++areadepth); }
158                                with (_root.map.areas[this._name]) {
159                                        clear();
160                                        enabled=false;
161                                        moveTo(this.path[0].x,this.path[0].y); 
162                                        if (f>-1) { beginFill(f,20); }
163                                                 else { lineStyle(linewidth*casingx,casingcol,100,false,"none"); }
164                                        for (var i=1; i<this.path.length; i+=1) {
165                                                lineTo(this.path[i].x,this.path[i].y);
166                                        }
167                                        if (f>-1) { endFill(); }
168                                };
169                        } else if (_root.map.areas[this._name]) {
170                                removeMovieClip(_root.map.areas[this._name]);
171                        }
172       
173                        // Draw line and tagged nodes
174       
175                        this.line.moveTo(this.path[0].x,this.path[0].y);
176                        for (var i=1; i<this.path.length; i+=1) {
177                                this.line.lineTo(this.path[i].x,this.path[i].y);
178                                if (this.path[i].tagged) {
179                                        // **** attach correct icon:
180                                        // if (this.path[i].attr['frog']) {
181                                        // this.taggednodes.attachMovie("poi_22",i,i);
182                                        // ...probably don't have to do _root.map.pois[point].__proto__=undefined;
183                                        //    because clicks are handled by the way movieclip
184                                        this.taggednodes.attachMovie("poiinway",i,i);
185                                        this.taggednodes[i]._x=this.path[i].x;
186                                        this.taggednodes[i]._y=this.path[i].y;
187                                        this.taggednodes[i]._xscale=this.taggednodes[i]._yscale=taggedscale;
188                                }
189                        }
190                        redrawRelationsForMember('way', this._name);
191                }
192        };
193
194        OSMWay.prototype.getFill=function() {
195                var f=-1; 
196                if (this.path[this.path.length-1]==this.path[0] && this.path.length>2) {
197                        if (this.attr['area']) { f='0x777777'; }
198                        var z=this.attr;
199                        for (var i in z) { if (areas[i] && this.attr[i]!='' && this.attr[i]!='coastline') { f=areas[i]; } }
200                }
201                return f;
202        };
203
204        // ---- Show direction
205
206        OSMWay.prototype.direction=function() {
207                if (this.path.length<2) {
208                        _root.panel.i_clockwise._visible=false;
209                        _root.panel.i_anticlockwise._visible=false;
210                        _root.panel.i_direction._visible=true;
211                        _root.panel.i_direction._alpha=50;
212                } else {
213                        var dx=this.path[this.path.length-1].x-this.path[0].x;
214                        var dy=this.path[this.path.length-1].y-this.path[0].y;
215                        if (dx!=0 || dy!=0) {
216                                // Non-circular
217                                _root.panel.i_direction._rotation=180-Math.atan2(dx,dy)*(180/Math.PI)-45;
218                                _root.panel.i_direction._alpha=100;
219                                _root.panel.i_direction._visible=true;
220                                _root.panel.i_clockwise._visible=false;
221                                _root.panel.i_anticlockwise._visible=false;
222                        } else {
223                                // Circular
224                                _root.panel.i_direction._visible=false;
225                                // Find lowest rightmost point
226                                // cf http://geometryalgorithms.com/Archive/algorithm_0101/
227                                var lowest=0;
228                                var xmax=-999999; var ymin=-999999;
229                                for (var i=0; i<this.path.length; i++) {
230                                        if      (this.path[i].y> ymin) { lowest=i; xmin=this.path[i].x; ymin=this.path[i].y; }
231                                        else if (this.path[i].y==ymin
232                                                  && this.path[i].x> xmax) { lowest=i; xmin=this.path[i].x; ymin=this.path[i].y; }
233                                }
234                                var clockwise=(this.onLeft(lowest)>0);
235                                _root.panel.i_clockwise._visible=clockwise;
236                                _root.panel.i_anticlockwise._visible=!clockwise;
237                        }
238                }
239        };
240
241        OSMWay.prototype.onLeft=function(j) {
242                var left=0;
243                if (this.path.length>=3) {
244                        var i=j-1; if (i==-1) { i=this.path.length-2; }
245                        var k=j+1; if (k==this.path.length) { k=1; }
246                        left=((this.path[j].x-this.path[i].x) * (this.path[k].y-this.path[i].y) -
247                                  (this.path[k].x-this.path[i].x) * (this.path[j].y-this.path[i].y));
248                }
249                return left;
250        };
251       
252
253        // ---- Remove from server
254       
255        OSMWay.prototype.remove=function() {
256                this.deleteMergedWays();
257                this.removeNodeIndex();
258                memberDeleted('way', this._name);
259                if (this._name>=0 && !_root.sandbox && !this.historic) {
260                        deleteresponder = function() { };
261                        deleteresponder.onResult = function(result) {
262                                var code=result.shift(); if (code) { handleError(code,result); return; }
263                                if (wayselected==result[0]) { deselectAll(); }
264                                removeMovieClip(_root.map.ways[result[0]]);
265                                removeMovieClip(_root.map.areas[result[0]]);
266                                _root.writesrequested--;
267                        };
268                        _root.writesrequested++;
269                        remote_write.call('deleteway',deleteresponder,_root.usertoken,_root.changeset,Math.floor(this._name));
270                } else {
271                        if (this._name==wayselected) { stopDrawing(); deselectAll(); }
272                        removeMovieClip(_root.map.areas[this._name]);
273                        removeMovieClip(this);
274                }
275        };
276
277        // ---- Variant with confirmation if any nodes have tags
278       
279        OSMWay.prototype.removeWithConfirm=function() {
280                var c=true;
281                var z=this.path;
282                for (var i in z) {
283                        if (this.path[i].tagged && hashLength(this.path[i].ways)==1) { c=false; }
284                }
285                if (c) {
286                        _root.ws.saveUndo(iText("deleting",'deleting'));
287                        this.remove();
288                } else {
289                        _root.windows.attachMovie("modal","confirm",++windowdepth);
290                        _root.windows.confirm.init(275,80,new Array(iText('Cancel','cancel'),iText('Delete','delete')),
291                                function(choice) {
292                                        if (choice==iText('Delete','delete')) { _root.ws.saveUndo(iText("deleting",'deleting')); _root.ws.remove(); }
293                                });
294                        _root.windows.confirm.box.createTextField("prompt",2,7,9,250,100);
295                        writeText(_root.windows.confirm.box.prompt,iText("Some of the points on this way are tagged. Really delete?",'prompt_taggedpoints'));
296                }
297        };
298
299        // ---- Upload to server
300       
301        OSMWay.prototype.upload=function() {
302                putresponder=function() { };
303                putresponder.onResult=function(result) {
304                        var code=result.shift(); if (code) { handleError(code,result); return; }
305                        var i,r,z,nw,ow,qway,qs,nodestodelete;
306                        ow=result[0];                   // old way ID
307                        nw=result[1];                   // new way ID
308                        if (ow!=nw) {   // renumber way?
309                                _root.map.ways[ow].renumberNodeIndex(nw);
310                                _root.map.ways[ow]._name=nw;
311                                renumberMemberOfRelation('way', result[0], nw);
312                                if (_root.map.areas[ow]) { _root.map.areas[ow]._name=nw; }
313                                if (_root.panel.t_details.text==ow) { _root.panel.t_details.text=nw; _root.panel.t_details.setTextFormat(plainText); }
314                                if (wayselected==ow) { selectWay(nw); }
315                        }
316                        // ** used to have bbox code here, but don't think we need it
317                        _root.map.ways[nw].uploading=false;
318                        _root.map.ways[nw].historic=false;
319                        _root.map.ways[nw].version=result[3];
320                       
321                        // renumber nodes (and any relations/ways they're in)
322                        z=result[2];
323                        for (var oid in z) {
324                                var nid = result[2][oid];
325                                nodes[oid].renumberTo(nid);
326                                nodes[nid].addWay(nw);
327                                renumberMemberOfRelation('node', oid, nid);
328                        }
329                        for (var oid in z) { delete _root.nodes[oid]; } // delete -ve nodes
330                        _root.map.ways[nw].clearPOIs();
331                        _root.map.ways[nw].deleteMergedWays();
332                        _root.writesrequested--;
333                        uploadDirtyWays();                      // make sure dependencies are uploaded
334                };
335                if (!this.uploading && !this.hasDependentNodes() && !this.locked && !_root.sandbox && this.path.length>1) {
336                        // Assemble 'sendpath' and upload it
337                        this.uploading=true;
338                        var sendpath=new Array();
339                        for (i=0; i<this.path.length; i++) {
340                                sendpath.push(new Array(coord2long(this.path[i].x),
341                                                                                coord2lat (this.path[i].y),
342                                                                                this.path[i].id,null,
343                                                                                deepCopy  (this.path[i].attr)));
344                        }
345                        _root.writesrequested++;
346                        remote_write.call('putway',putresponder,_root.usertoken,_root.changeset,Number(this._name),sendpath,this.attr);
347                        this.clean=true;
348                }
349        };
350
351        // ---- Delete any ways merged into this one
352
353        OSMWay.prototype.deleteMergedWays=function() {
354                while (this.mergedways.length>0) {
355                        var i=this.mergedways.shift();
356                        _root.map.ways.attachMovie("way",i,++waydepth); // can't remove unless the movieclip exists!
357                        _root.map.ways[i].remove();
358                }
359        };
360
361        // ---- Revert to copy in database
362       
363        OSMWay.prototype.reload=function() {
364                _root.waysrequested+=1;
365                while (this.mergedways.length>0) {
366                        var i=this.mergedways.shift();
367                        _root.waysrequested+=1;
368                        _root.map.ways.attachMovie("way",i,++waydepth);
369                        _root.map.ways[i].load();
370                }
371                this.checkconnections=true;
372                this.load();
373        };
374       
375        // ---- Save for undo
376
377        OSMWay.prototype.saveUndo=function(str) {
378                _root.undo.append(UndoStack.prototype.undo_deleteway,
379                                                  new Array(this._name,this._x,this._y,
380                                                                        deepCopy(this.attr),
381                                                                        deepCopy(this.path)),iText("$1 a way",'a_way',str));
382        };
383
384
385        // ---- Click handling 
386
387        OSMWay.prototype.onRollOver=function() {
388                if (this._name!=_root.wayselected && _root.drawpoint>-1) {
389                        this.highlightPoints(5001,"anchorhint");
390                        setPointer('penplus');
391                } else if (_root.drawpoint>-1) { setPointer('penplus'); }
392                                                                  else { setPointer(''); }
393        };
394       
395        OSMWay.prototype.onRollOut=function() {
396                if (_root.wayselected) { setPointer(''   ); }
397                                                  else { setPointer('pen'); }
398                _root.map.anchorhints.removeMovieClip();
399        };
400       
401        OSMWay.prototype.onPress=function() {
402                removeWelcome(true);
403                if (Key.isDown(Key.SHIFT) && this._name==_root.wayselected && _root.drawpoint==-1) {
404                        // shift-click current way: insert point
405                        this.insertAnchorPointAtMouse();
406                } else if (Key.isDown(Key.SHIFT) && _root.wayselected && this.name!=_root.wayselected && _root.drawpoint==-1) {
407                        if (_root.ws.hitTest(_root._xmouse,_root._ymouse,true)) {
408                                // shift-click other way (at intersection with current): make intersection
409                                this.insertAnchorPointAtMouse();
410                        } else {
411                                // shift-click other way: merge two ways
412                                this.mergeAtCommonPoint(_root.ws);
413                                _root.ws.redraw();
414                                _root.ws.select();
415//                              _root.ws.upload();
416//                              _root.map.ways[this._name ].remove(wayselected);
417                        }
418                } else if (_root.drawpoint>-1) {
419                        // click other way while drawing: insert point as junction
420                        if (!this.historic) {
421                                if (this._name==_root.wayselected && _root.drawpoint>0) {
422                                        _root.drawpoint+=1;     // inserting node earlier into the way currently being drawn
423                                }
424                                _root.newnodeid--;
425                                _root.nodes[newnodeid]=new Node(newnodeid,0,0,new Object());
426                                this.insertAnchorPoint(_root.nodes[newnodeid]);
427                                this.highlightPoints(5001,"anchorhint");
428                                addEndPoint(_root.nodes[newnodeid]);
429                        }
430                        _root.junction=true;
431                        restartElastic();
432                } else {
433                        // click way: select
434                        _root.panel.properties.saveAttributes();
435                        this.select();
436                        clearTooltip();
437                        _root.clicktime=new Date();
438                        // was the click on a tagged node? if so, select directly
439                        var n;
440                        for (var i=0; i<this.path.length; i+=1) {
441                                if (this.taggednodes[i].hitTest(_root._xmouse,_root._ymouse,true)) { n=i; }
442                        }
443                        if (n) { _root.map.anchors[n].beginDrag();
444                                         _root.map.anchors[n].select(); }
445                          else { this.beginDrag(); }
446                }
447        };
448
449        OSMWay.prototype.beginDrag=function() {
450                this.onMouseMove=function() { this.trackDrag(); };
451                this.onMouseUp  =function() { this.endDrag();   };
452                this.dragged=false;
453                this.held=true;
454                _root.firstxmouse=_root.map._xmouse;
455                _root.firstymouse=_root.map._ymouse;
456        };
457
458        OSMWay.prototype.trackDrag=function() {
459                var t=new Date();
460                var longclick=(t.getTime()-_root.clicktime)>1000;
461                var xdist=Math.abs(_root.map._xmouse-_root.firstxmouse);
462                var ydist=Math.abs(_root.map._ymouse-_root.firstymouse);
463                // Don't enable drag unless way held for a while after click
464                if ((xdist>=tolerance   || ydist>=tolerance  ) &&
465                        (t.getTime()-_root.clicktime)<300 &&
466                        lastwayselected!=wayselected) { this.held=false; }
467                // Move way if dragged a long way, or dragged a short way after a while
468                if ((xdist>=tolerance*4 || ydist>=tolerance*4) ||
469                   ((xdist>=tolerance/4 || ydist>=tolerance/4) && longclick) &&
470                   this.held) {
471                        this.dragged=true;
472                }
473                if (this.dragged) {
474                        _root.map.anchors._x=_root.map.areas[this._name]._x=_root.map.highlight._x=this._x=_root.map._xmouse-_root.firstxmouse;
475                        _root.map.anchors._y=_root.map.areas[this._name]._y=_root.map.highlight._y=this._y=_root.map._ymouse-_root.firstymouse;
476                }
477        };
478       
479        OSMWay.prototype.endDrag=function() {
480                delete this.onMouseMove;
481                delete this.onMouseUp;
482                _root.map.anchors._x=_root.map.areas[this._name]._x=_root.map.highlight._x=this._x=0;
483                _root.map.anchors._y=_root.map.areas[this._name]._y=_root.map.highlight._y=this._y=0;
484                if (this.dragged) {
485                        this.moveNodes(_root.map._xmouse-_root.firstxmouse,_root.map._ymouse-_root.firstymouse);
486                        setAdvice(false,iText("Way dragged (Z to undo)",'advice_waydragged'));
487                        this.redraw();
488                        this.select();
489                        _root.undo.append(UndoStack.prototype.undo_movenodes,
490                                                          new Array(this,_root.map._xmouse-_root.firstxmouse,
491                                                                                         _root.map._ymouse-_root.firstymouse),
492                                                          iText("moving a way",'action_moveway'));
493                }
494        };
495       
496        // ---- Select/highlight
497       
498        OSMWay.prototype.select=function() {
499                _root.panel.properties.tidy();
500                if (_root.wayselected!=this._name || _root.poiselected!=0) { uploadSelected(); }
501//              _root.panel.properties.saveAttributes();
502                selectWay(this._name);
503                _root.pointselected=-2;
504                _root.poiselected=0;
505                this.highlightPoints(5000,"anchor");
506                removeMovieClip(_root.map.anchorhints);
507                this.highlight();
508                setTypeText(iText("Way",'way'),this._name);
509                _root.panel.properties.init('way',getPanelColumns(),4);
510                _root.panel.presets.init(_root.panel.properties);
511                updateButtons();
512                updateScissors(false);
513        };
514       
515        OSMWay.prototype.highlight=function() {
516                _root.map.createEmptyMovieClip("highlight",5);
517                if (_root.pointselected>-2) {
518                        highlightSquare(_root.map.anchors[pointselected]._x,_root.map.anchors[pointselected]._y,8/Math.pow(2,Math.min(_root.scale,17)-13));
519                } else {
520                        var linecolour=0xFFFF00; if (this.locked) { var linecolour=0x00FFFF; }
521                        _root.map.highlight.lineStyle(linewidth*1.5+8,linecolour,80,false,"none");
522                        _root.map.highlight.moveTo(this.path[0].x,this.path[0].y);
523                        for (var i=1; i<this.path.length; i+=1) {
524                                _root.map.highlight.lineTo(this.path[i].x,this.path[i].y);
525                        }
526                }
527                this.direction();
528        };
529
530        OSMWay.prototype.highlightPoints=function(d,atype) {
531                var enlarge=1;
532                var anchorsize=120/Math.pow(2,_root.scale-13);
533                if (preferences.data.thinlines) { enlarge=0.5; }
534                if (_root.scale>15) {
535                        switch (_root.scale) {
536                                case 15: anchorsize+=10*enlarge; break;
537                                case 16: anchorsize+=7 *enlarge; break;
538                                case 17: anchorsize+=5 *enlarge; break;
539                                case 18: anchorsize+=6 *enlarge; break;
540                                case 19: anchorsize+=6 *enlarge; break;
541                        }
542                }
543                var group=atype+"s";
544                _root.map.createEmptyMovieClip(group,d);
545                for (var i=0; i<this.path.length; i+=1) {
546                        _root.map[group].attachMovie(atype,i,i);
547                        _root.map[group][i]._x=this.path[i].x;
548                        _root.map[group][i]._y=this.path[i].y;
549                        _root.map[group][i]._xscale=anchorsize;
550                        _root.map[group][i]._yscale=anchorsize;
551                        _root.map[group][i].node=this.path[i].id;
552                        _root.map[group][i].way=this;
553                        if (this.path[i].tagged) {
554                                // anchor point should be black if it has tags
555                                _root.map[group][i].blacken=new Color(_root.map[group][i]);
556                                _root.map[group][i].blacken.setTransform(to_black);
557                        }
558                }
559        };
560
561        // ---- Split, merge, reverse
562
563        OSMWay.prototype.splitWay=function(point,newattr) {
564                var i,z;
565                if (point>0 && point<(this.path.length-1) && !this.historic) {
566                        _root.newwayid--;                                                                                       // create new way
567                        _root.map.ways.attachMovie("way",newwayid,++waydepth);          //  |
568                        _root.map.ways[newwayid].path=shallowCopy(this.path);           // deep copy path array
569                        this.removeNodeIndex();
570
571                        if (newattr) { _root.map.ways[newwayid].attr=newattr; }
572                                        else { _root.map.ways[newwayid].attr=deepCopy(this.attr); }
573
574                        z=getRelationsForWay(this._name);                                                       // copy relations
575                        for (i in z) {                                                                                          //  |
576                                _root.map.relations[z[i]].setWayRole(newwayid,_root.map.relations[z[i]].getWayRole(this._name));
577                        }                                                                                                                       //  |
578
579                        this.path.splice(Math.floor(point)+1);                                          // current way
580                        this.redraw();                                                                                          //  |
581                        this.createNodeIndex();
582
583                        _root.map.ways[newwayid].path.splice(0,point);                          // new way
584                        _root.map.ways[newwayid].locked=this.locked;                            //  |
585                        _root.map.ways[newwayid].redraw();                                                      //  |
586                        _root.map.ways[newwayid].upload();                                                      //  |
587                        _root.map.ways[newwayid].createNodeIndex();                                     //  |
588
589                        this.upload();                                                                                          // upload current way
590                        this.select();                                                                                          //  |
591                        uploadDirtyRelations();
592                        _root.undo.append(UndoStack.prototype.undo_splitway,
593                                                          new Array(this,_root.map.ways[newwayid]),
594                                                          iText("splitting a way",'action_splitway'));
595                };
596        };
597
598        //              Merge (start/end of this way,other way object,start/end of other way)
599
600        OSMWay.prototype.mergeWay=function(topos,otherway,frompos) {
601                var i,z;
602                var conflict=false;
603                if (this.historic || otherway.historic) { return; }
604
605                var mergepoint=this.path.length;
606                if (topos==0) {
607                        _root.undo.append(UndoStack.prototype.undo_mergeways,
608                                                          new Array(this,deepCopy(otherway.attr),deepCopy(this.attr),frompos),
609                                                          iText("merging two ways",'action_mergeways'));
610                } else {
611                        _root.undo.append(UndoStack.prototype.undo_mergeways,
612                                                          new Array(this,deepCopy(this.attr),deepCopy(otherway.attr),topos),
613                                                          iText("merging two ways",'action_mergeways'));
614                }
615                if (frompos==0) { for (i=0; i<otherway.path.length;    i+=1) { this.addPointFrom(topos,otherway,i); } }
616                                   else { for (i=otherway.path.length-1; i>=0; i-=1) { this.addPointFrom(topos,otherway,i); } }
617
618                z=otherway.attr;
619                for (i in z) {
620                        if (otherway.attr[i].substr(0,6)=='(type ') { otherway.attr[i]=null; }
621                        if (this.attr[i].substr(0,6)=='(type ') { this.attr[i]=null; }
622                        if (this.attr[i]) {
623                                if (this.attr[i]!=otherway.attr[i] && otherway.attr[i]) { this.attr[i]+='; '+otherway.attr[i]; conflict=true; }
624                        } else {
625                                this.attr[i]=otherway.attr[i];
626                        }
627                        if (!this.attr[i]) { delete this.attr[i]; }
628                }
629
630                z=getRelationsForWay(otherway._name);                                           // copy relations
631                for (i in z) {                                                                                          //  |
632                        if (!_root.map.relations[z[i]].hasWay(this._name)) {    //  |
633                                _root.map.relations[z[i]].setWayRole(this._name,_root.map.relations[z[i]].getWayRole(otherway._name));
634                        }                                                                                                               //  |
635                }                                                                                                                       //  |
636
637                this.mergedways.push(otherway._name);
638                this.mergedways.concat(otherway.mergedways);
639                this.clean=false;
640                markClean(false);
641                if (otherway.locked) { this.locked=true; }
642                removeMovieClip(_root.map.areas[otherway._name]);
643                removeMovieClip(otherway);
644                if (this._name==_root.wayselected) { 
645                        _root.panel.properties.reinit();
646                }
647                if (conflict) { setAdvice(false,iText("Tags don't match - please check (Z to undo)",'advice_tagconflict')); }
648        };
649
650        OSMWay.prototype.addPointFrom=function(topos,otherway,srcpt) {
651                if (topos==0) { if (this.path[0                                 ]==otherway.path[srcpt]) { return; } }  // don't add duplicate points
652                                 else { if (this.path[this.path.length-1]==otherway.path[srcpt]) { return; } }  //  |
653                if (topos==0) { this.path.unshift(otherway.path[srcpt]); }
654                             else { this.path.push(otherway.path[srcpt]); }
655                otherway.path[srcpt].addWay(this._name);
656        };
657
658        OSMWay.prototype.mergeAtCommonPoint=function(sel) {
659                var selstart =sel.path[0];
660                var sellen   =sel.path.length-1;
661                var selend   =sel.path[sellen];
662                var thisstart=this.path[0];
663                var thislen  =this.path.length-1;
664                var thisend  =this.path[thislen];
665                if      (selstart==thisstart) { sel.mergeWay(0,this,0);                    return true; }
666                else if (selstart==thisend  ) { sel.mergeWay(0,this,thislen);      return true; }
667                else if (selend  ==thisstart) { sel.mergeWay(sellen,this,0);       return true; }
668                else if (selend  ==thisend  ) { sel.mergeWay(sellen,this,thislen); return true; }
669                else                                              { setAdvice(true,iText("The ways do not share a common point",'advice_nocommonpoint')); return false; }
670        };
671
672        // ---- Reverse order
673       
674        OSMWay.prototype.reverseWay=function() {
675                if (this.path.length<2) { return; }
676                if (_root.drawpoint>-1) { _root.drawpoint=(this.path.length-1)-_root.drawpoint; }
677                this.path.reverse();
678                this.redraw();
679                this.direction();
680                this.select();
681                this.clean=false;
682                markClean(false);
683                _root.undo.append(UndoStack.prototype.undo_reverse,new Array(this),iText("reversing a way",'action_reverseway'));
684        };
685
686        // ---- Move all nodes within a way
687       
688        OSMWay.prototype.moveNodes=function(xdiff,ydiff) {
689                var i,n;
690                var movedalready=new Array();
691                this.clean=false;
692                markClean(false);
693                for (i=0; i<this.path.length; i+=1) {
694                        n=this.path[i].id;
695                        if (movedalready[n]) {
696                        } else {
697                                this.path[i].moveTo(this.path[i].x+xdiff,
698                                                                        this.path[i].y+ydiff,
699                                                                        this._name);
700                                movedalready[n]=true;
701                        }
702                }
703        };
704
705        // ---- Check for duplicates (e.g. when C is removed from ABCB)
706       
707        OSMWay.prototype.removeDuplicates=function() {
708                var z=this.path; var ch=false;
709                for (var i in z) {
710                        if (i>0) {
711                                if (this.path[i]==this.path[i-1]) { this.path.splice(i,1); ch=true; }
712                        }
713                }
714                return ch;
715        };
716
717        // ---- Add point into way with SHIFT-clicking
718        //              cf http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/source.vba
719        //              for algorithm to find nearest point on a line
720       
721        OSMWay.prototype.insertAnchorPoint=function(nodeobj) {
722                var nx,ny,u,closest,closei,i,a,b,direct,via,newpoint;
723                nx=_root.map._xmouse;   // where we're inserting it
724                ny=_root.map._ymouse;   //      |
725                closest=0.1; closei=0;
726                for (i=0; i<(this.path.length)-1; i+=1) {
727                        a=this.path[i  ];
728                        b=this.path[i+1];
729                        direct=Math.sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
730                        via   =Math.sqrt((nx -a.x)*(nx -a.x)+(ny -a.y)*(ny -a.y));
731                        via  +=Math.sqrt((nx -b.x)*(nx -b.x)+(ny -b.y)*(ny -b.y));
732                        if (Math.abs(via/direct-1)<closest) {
733                                closei=i+1;
734                                closest=Math.abs(via/direct-1);
735                                u=((nx-a.x)*(b.x-a.x)+
736                                   (ny-a.y)*(b.y-a.y))/
737                                   (Math.pow(b.x-a.x,2)+Math.pow(b.y-a.y,2));
738                                nodeobj.x=a.x+u*(b.x-a.x);
739                                nodeobj.y=a.y+u*(b.y-a.y);
740                        }
741                }
742                // Insert
743                nodeobj.addWay(this._name);
744                this.path.splice(closei,0,nodeobj);
745                this.clean=false;
746                this.redraw();
747                markClean(false);
748//              _root.adjustedxmouse=tx;        // in case we're adding extra points...
749//              _root.adjustedymouse=ty;        // should probably return an array or an object **
750                return closei;
751        };
752
753        //              Wrapper around the above to:
754        //              - insert at mouse position
755        //              - add to undo stack
756        //              - add intersection at any crossing ways
757
758        OSMWay.prototype.insertAnchorPointAtMouse=function() {
759                _root.newnodeid--;
760                _root.nodes[newnodeid]=new Node(newnodeid,0,0,new Object());
761                _root.pointselected=this.insertAnchorPoint(_root.nodes[newnodeid]);
762                var waylist=new Array(); waylist.push(this);
763                var poslist=new Array(); poslist.push(_root.pointselected);
764                for (qway in _root.map.ways) {
765                        if (_root.map.ways[qway].hitTest(_root._xmouse,_root._ymouse,true) && qway!=this._name) {
766                                poslist.push(_root.map.ways[qway].insertAnchorPoint(_root.nodes[newnodeid]));
767                                waylist.push(_root.map.ways[qway]);
768                        }
769                }
770                _root.undo.append(UndoStack.prototype.undo_addpoint,
771                                                  new Array(waylist,poslist), iText("adding a node into a way",'action_insertnode'));
772                _root.ws.highlightPoints(5000,"anchor");
773                _root.map.anchors[pointselected].beginDrag();
774        };
775
776        // ---- Remove point from this way (only)
777       
778        OSMWay.prototype.removeAnchorPoint=function(point) {
779                // ** if length<2, then mark as way removal
780                _root.undo.append(UndoStack.prototype.undo_deletepoint,
781                                                  new Array(deepCopy(this.path[point]),
782                                                                        new Array(this._name),
783                                                                        new Array(point)),
784                                                  iText("deleting a point",'action_deletepoint'));
785                this.path[point].removeWay(this._name);
786                this.path.splice(point,1);
787                this.removeDuplicates();
788                if (this.path.length<2) { this.remove(); }
789                                                   else { this.redraw(); this.clean=false; }
790        };
791
792        // ---- Bounding box utility functions
793
794        OSMWay.prototype.resetBBox=function() {
795                this.xmin=this.ymin= 999;
796                this.xmax=this.ymax=-999;
797        };
798       
799        OSMWay.prototype.updateBBox=function(long,lat) {
800                this.xmin=Math.min(long,this.xmin);
801                this.xmax=Math.max(long,this.xmax);
802                this.ymin=Math.min(lat ,this.ymin);
803                this.ymax=Math.max(lat ,this.ymax);
804        };
805
806        // ---- Node->way associations
807       
808        OSMWay.prototype.createNodeIndex  =function() { var z=this.path; for (var i in z) { this.path[i].addWay(this._name);    } };
809        OSMWay.prototype.removeNodeIndex  =function() { var z=this.path; for (var i in z) { this.path[i].removeWay(this._name); } };
810        OSMWay.prototype.renumberNodeIndex=function(n) {
811                var z=this.path; for (i in z) { 
812                        this.path[i].removeWay(this._name);
813                        this.path[i].addWay(n);
814                }
815        };
816        OSMWay.prototype.hasDependentNodes=function() {
817                var d=false;
818                var z=this.path; for (var i in z) {
819                        if (this.path[i].id<0) {
820                                var ways=this.path[i].ways; for (var w in ways) {
821                                        if (_root.map.ways[w].uploading) { d=true; }
822                                }
823                        }
824                }
825                return d;
826        };
827
828        // =====================================================================================
829        // Offset path
830        // ** much of the dialogue box could be refactored to share with relations dialogue
831
832        function askOffset() {
833                if (!_root.wayselected) { return; }
834                _root.windows.attachMovie("modal","offset",++windowdepth);
835                _root.windows.offset.init(300, 170, [iText("Cancel",'cancel'), iText("Ok",'ok')], completeOffset);
836                var z = 5;
837                var box = _root.windows.offset.box;
838               
839                box.createTextField("title",z++,7,7,300-14,20);
840                box.title.text = iText("Create parallel way",'prompt_createparallel');
841                with (box.title) {
842                        wordWrap=true;
843                        setTextFormat(boldText);
844                        selectable=false; type='dynamic';
845                }
846               
847                box.createTextField("instr",z++,7,30,300-14,40);
848
849                // Create radio buttons and menu
850
851                box.attachMovie("radio","offsetoption",z++);
852                box.offsetoption.addButton(10,35 ,iText("Dual carriageway (D2)",'offset_dual'));
853                box.offsetoption.addButton(10,55 ,iText("Motorway (D3)",'offset_motorway'));
854                box.offsetoption.addButton(10,75 ,iText("Narrow canal towpath",'offset_narrowcanal'));
855                box.offsetoption.addButton(10,95 ,iText("Broad canal towpath",'offset_broadcanal'));
856                box.offsetoption.addButton(10,115,iText("Choose offset (m)",'offset_choose'));
857                box.offsetoption.select(1);
858
859                var w=box.offsetoption[5].prompt._width+25;
860                box.createTextField("useroffset",z++,w,110,290-w,17);
861                box.useroffset.setNewTextFormat(plainSmall);
862                box.useroffset.type='input';
863                box.useroffset.backgroundColor=0xDDDDDD;
864                box.useroffset.background=true;
865                box.useroffset.border=true;
866                box.useroffset.borderColor=0xFFFFFF;
867                box.useroffset.onSetFocus=function() { this._parent.offsetoption.select(5); };
868        }
869
870        // typical widths:
871        // central reservation:
872        //       4.5m on a rural motorway/dual carriageway
873        //       3.5m on an urban motorway
874        //       1.8m on an urban dual carriageway
875        // lane widths are typically always 3.65m
876        // hard shoulders are typically 3.30m
877        // hard strips are typically 1m
878
879        function completeOffset(button) {
880                if (button!=iText("Ok",'ok')) { return false; }
881                var radio=_root.windows.offset.box.offsetoption.selected;
882                var m;
883                if (radio==5) {
884                        m=_root.windows.offset.box.useroffset.text;
885                        if (!button) { return false; }
886                } else {
887                        m=new Array(0,4.5+3.65*2,4.5+3.65*3,5.5,11);
888                        m=m[radio];
889                }
890                var thislat=coord2lat(_root.map._y);                    // near as dammit
891                var latfactor=Math.cos(thislat/(180/Math.PI));  // 111200m in a degree at the equator
892                m=masterscale/(111200*latfactor)*m;                             // 111200m*cos(lat in radians) elsewhere
893                _root.ws.offset( m);
894                _root.ws.offset(-m);
895                _root.undo.append(UndoStack.prototype.undo_makeways,
896                                                  new Array(_root.newwayid,_root.newwayid+1),
897                                                  iText("creating parallel ways",'action_createparallel'));
898        }
899
900        // Create (locked) offset way
901        // offset is + or - depending on which side
902
903        OSMWay.prototype.offset=function(tpoffset) {
904                var a,b,o,df,x,y;
905                var offsetx=new Array();
906                var offsety=new Array();
907                var wm=1;       // was 10 before
908
909                _root.newwayid--;                                                                                       // create new way
910                _root.map.ways.attachMovie("way",newwayid,++waydepth);          //  |
911                var nw=_root.map.ways[newwayid];
912                nw.locked=true;
913                nw.clean=false;
914
915                // Normalise, and calculate offset vectors
916
917                for (var i=0; i<this.path.length; i++) {
918                        a=this.path[i  ].y - this.path[i+1].y;
919                        b=this.path[i+1].x - this.path[i  ].x;
920                        h=Math.sqrt(a*a+b*b);
921                        if (h!=0) { a=a/h; b=b/h; }
922                                 else { a=0; b=0; }
923                        offsetx[i]=wm*a;
924                        offsety[i]=wm*b;
925                }
926
927                _root.newnodeid--;
928                _root.nodes[newnodeid]=new Node(newnodeid,this.path[0].x+tpoffset*offsetx[0],
929                                                                                                  this.path[0].y+tpoffset*offsety[0],
930                                                                                                  new Object());
931                nw.path.push(_root.nodes[newnodeid]);
932               
933                for (i=1; i<(this.path.length-1); i++) {
934       
935                        a=det(offsetx[i]-offsetx[i-1],
936                                  offsety[i]-offsety[i-1],
937                                  this.path[i+1].x - this.path[i  ].x,
938                                  this.path[i+1].y - this.path[i  ].y);
939                        b=det(this.path[i  ].x - this.path[i-1].x,
940                                  this.path[i  ].y - this.path[i-1].y,
941                                  this.path[i+1].x - this.path[i  ].x,
942                                  this.path[i+1].y - this.path[i  ].y);
943                        if (b!=0) { df=a/b; } else { df=0; }
944                       
945                        x=this.path[i].x + tpoffset*(offsetx[i-1]+df*(this.path[i].x - this.path[i-1].x));
946                        y=this.path[i].y + tpoffset*(offsety[i-1]+df*(this.path[i].y - this.path[i-1].y));
947       
948                        _root.newnodeid--;
949                        _root.nodes[newnodeid]=new Node(newnodeid,x,y,new Object());
950                        nw.path.push(_root.nodes[newnodeid]);
951                }
952       
953                _root.newnodeid--;
954                _root.nodes[newnodeid]=new Node(newnodeid,this.path[i].x+tpoffset*offsetx[i-1],
955                                                                                                  this.path[i].y+tpoffset*offsety[i-1],new Object());
956                nw.path.push(_root.nodes[newnodeid]);
957                nw.redraw();
958        };
959
960    function det(a,b,c,d) { return a*d-b*c; }
961
962
963        Object.registerClass("way",OSMWay);
964
965
966        // =====================================================================================
967        // Drawing support functions
968
969        // removeNodeFromWays - now see Node.removeFromAllWays
970
971        // startNewWay            - create new way from first node
972
973        function startNewWay(node) {
974                uploadSelected();
975                _root.newwayid--;
976                selectWay(newwayid);
977                _root.poiselected=0;
978                _root.map.ways.attachMovie("way",newwayid,++waydepth);
979                _root.map.ways[newwayid].path[0]=_root.nodes[node];
980                _root.map.ways[newwayid].redraw();
981                _root.map.ways[newwayid].select();
982                _root.map.ways[newwayid].clean=false;
983                _root.nodes[node].addWay(newwayid);
984                _root.map.anchors[0].startElastic();
985                _root.drawpoint=0;
986                markClean(false);
987                setTooltip(iText("click to add point\ndouble-click/Return\nto end line",'hint_drawmode'),0);
988        }
989
990        // addEndPoint(node object) - add point to start/end of line
991
992        function addEndPoint(node) {
993                var drawnode=_root.ws.path[_root.drawpoint];
994                if (_root.drawpoint==_root.ws.path.length-1) {
995                        _root.ws.path.push(node);
996                        _root.drawpoint=_root.ws.path.length-1;
997                } else {
998                        _root.ws.path.unshift(node);    // drawpoint=0, add to start
999                }
1000                node.addWay(_root.wayselected);
1001       
1002                // Redraw line (if possible, just extend it to save time)
1003                if (_root.ws.getFill()>-1 || 
1004                        _root.ws.path.length<3 ||
1005                        _root.pointselected>-2) {
1006                        _root.ws.redraw();
1007                        _root.ws.select();
1008                } else {
1009                        _root.ws.line.moveTo(drawnode.x,drawnode.y);
1010                        _root.ws.line.lineTo(node.x,node.y);
1011                        if (casing[_root.ws.attr['highway']]) {
1012                                _root.map.areas[wayselected].moveTo(drawnode.x,drawnode.y);
1013                                _root.map.areas[wayselected].lineTo(node.x,node.y);
1014                        }
1015                        _root.map.highlight.moveTo(drawnode.x,drawnode.y);
1016                        _root.map.highlight.lineTo(node.x,node.y);
1017                        _root.ws.direction();
1018                        _root.ws.highlightPoints(5000,"anchor");
1019                        removeMovieClip(_root.map.anchorhints);
1020                }
1021                redrawRelationsForMember('way',_root.wayselected);
1022                // Mark as unclean
1023                _root.ws.clean=false;
1024                markClean(false);
1025                _root.map.elastic.clear();
1026                var poslist=new Array(); poslist.push(_root.drawpoint);
1027                _root.undo.append(UndoStack.prototype.undo_addpoint,
1028                                                  new Array(new Array(_root.ws),poslist),
1029                                                  iText("adding a node to the end of a way",'action_addpoint'));
1030        }
1031
1032        function stopDrawing() {
1033                _root.map.anchors[_root.drawpoint].endElastic();
1034                _root.drawpoint=-1;
1035                if (_root.ws.path.length<=1) { 
1036                        // way not long enough, so abort
1037                        _root.ws.removeNodeIndex();
1038                        removeMovieClip(_root.map.areas[wayselected]);
1039                        removeMovieClip(_root.ws);
1040                        removeMovieClip(_root.map.anchors);
1041                }
1042                _root.map.elastic.clear();
1043                clearTooltip();
1044        };
1045
1046        // cycleStacked - cycle through ways sharing same point
1047
1048        function cycleStacked() {
1049                if (_root.pointselected>-2) {
1050                        stopDrawing();
1051                        var id=_root.ws.path[_root.pointselected].id;
1052                        var firstfound=0; var nextfound=0;
1053                        for (qway in _root.map.ways) {
1054                                if (qway!=_root.wayselected) {
1055                                        for (qs=0; qs<_root.map.ways[qway].path.length; qs+=1) {
1056                                                if (_root.map.ways[qway].path[qs].id==id) {
1057                                                        var qw=Math.floor(qway);
1058                                                        if (firstfound==0 || qw<firstfound) { firstfound=qw; }
1059                                                        if ((nextfound==0 || qw<nextfound) && qw>wayselected) { nextfound=qw; }
1060                                                }
1061                                        }
1062                                }
1063                        }
1064                        if (firstfound) {
1065                                if (nextfound==0) { var nextfound=firstfound; }
1066                                _root.map.ways[nextfound].swapDepths(_root.ws);
1067                                _root.map.ways[nextfound].select();
1068                        }
1069                }
1070        };
1071
1072        // ================================================================
1073        // Way communication
1074       
1075        // whichWays    - get list of ways from remoting server
1076
1077        function whichWays() {
1078                _root.lastwhichways=new Date();
1079                if (_root.waycount>500) { purgeWays(); }
1080                if (_root.poicount>500) { purgePOIs(); }
1081                if (_root.edge_l>_root.bigedge_l &&
1082                        _root.edge_r<_root.bigedge_r &&
1083                        _root.edge_b>_root.bigedge_b &&
1084                        _root.edge_t<_root.bigedge_t) {
1085                        // we have already loaded this area, so ignore
1086                } else {
1087                        whichresponder=function() {};
1088                        whichresponder.onResult=function(result) {
1089                                var code=result.shift(); if (code) { handleError(code,result); return; }
1090                                _root.whichreceived+=1;
1091                                waylist  =result[0];
1092                                pointlist=result[1];
1093                                relationlist=result[2];
1094
1095                                for (i in waylist) {                                                                            // ways
1096                                        way=waylist[i][0];                                                                              //  |
1097                                        if (!_root.map.ways[way] || _root.map.ways[way].version!=waylist[i][1]) {
1098                                                _root.map.ways.attachMovie("way",way,++waydepth);       //  |
1099                                                _root.map.ways[way].load();                                                     //  |
1100                                                _root.waycount+=1;                                                                      //  |
1101                                                _root.waysrequested+=1;                                                         //  |
1102                                        }
1103                                }
1104                               
1105                                for (i in pointlist) {                                                                          // POIs
1106                                        point=pointlist[i][0];                                                                  //  |
1107                                        if (!_root.map.pois[point] || _root.map.pois[point].version!=pointlist[i][4]) {
1108                                                // **** attach correct icon:
1109                                                // if (pointlist[i][3]["place"]) {
1110                                                // _root.map.pois.attachMovie("poi_22",point,++poidepth);
1111                                                _root.map.pois.attachMovie("poi",point,++poidepth);     //  |
1112                                                _root.map.pois[point]._x=long2coord(pointlist[i][1]);// |
1113                                                _root.map.pois[point]._y=lat2coord (pointlist[i][2]);// |
1114                                                _root.map.pois[point]._xscale=
1115                                                _root.map.pois[point]._yscale=Math.max(100/Math.pow(2,_root.scale-13),6.25);
1116                                                _root.map.pois[point].version=pointlist[i][4];          //  |
1117                                                _root.map.pois[point].attr=pointlist[i][3];                     //  |
1118                                                _root.poicount+=1;                                                                      //  |
1119                                                if (point==prenode) { deselectAll(); prenode=undefined;
1120                                                                                          _root.map.pois[point].select(); }
1121                                        }
1122                                }
1123
1124                                for (i in relationlist) {
1125                                        rel = relationlist[i][0];
1126                    if (!_root.map.relations[rel] || _root.map.relations[rel].version!=relationlist[i][1]) {
1127                                                _root.map.relations.attachMovie("relation",rel,++reldepth);
1128                                                _root.map.relations[rel].load();
1129                                                _root.relcount+=1;
1130                                                _root.relsrequested+=1;
1131                                        }
1132                }
1133                        };
1134                        remote_read.call('whichways',whichresponder,_root.edge_l,_root.edge_b,_root.edge_r,_root.edge_t);
1135                        _root.bigedge_l=_root.edge_l; _root.bigedge_r=_root.edge_r;
1136                        _root.bigedge_b=_root.edge_b; _root.bigedge_t=_root.edge_t;
1137                        _root.whichrequested+=1;
1138                }
1139        }
1140
1141        // purgeWays - remove any clean ways outside current view
1142       
1143        function purgeWays() {
1144                for (qway in _root.map.ways) {
1145                        if (qway==_root.wayselected) {
1146                        } else if (!_root.map.ways[qway].clean) {
1147                                _root.map.ways[qway].upload();
1148                                uploadDirtyRelations();
1149                        } else if (((_root.map.ways[qway].xmin<edge_l && _root.map.ways[qway].xmax<edge_l) ||
1150                                                (_root.map.ways[qway].xmin>edge_r && _root.map.ways[qway].xmax>edge_r) ||
1151                                            (_root.map.ways[qway].ymin<edge_b && _root.map.ways[qway].ymax<edge_b) ||
1152                                                (_root.map.ways[qway].ymin>edge_t && _root.map.ways[qway].ymax>edge_t))) {
1153                                removeMovieClip(_root.map.ways[qway]);
1154                                removeMovieClip(_root.map.areas[qway]);
1155                                _root.waycount-=1;
1156                        }
1157                }
1158                _root.bigedge_l=_root.edge_l; _root.bigedge_r=_root.edge_r;
1159                _root.bigedge_b=_root.edge_b; _root.bigedge_t=_root.edge_t;
1160                // ** remove unused nodes (i.e. this.ways only contains dead ones)
1161        }
1162
1163        function selectWay(id) {
1164                _root.lastwayselected=_root.wayselected;
1165                _root.wayselected=Math.floor(id);
1166                _root.ws=_root.map.ways[id];
1167        }
Note: See TracBrowser for help on using the repository browser.