Ticket #5577: intersect_way.patch

File intersect_way.patch, 24.8 KB (added by Upliner, 15 years ago)
  • src/org/openstreetmap/josm/actions/AddIntersectionsAction.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.actions;
     3
     4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
     5import static org.openstreetmap.josm.tools.I18n.tr;
     6
     7import java.awt.event.ActionEvent;
     8import java.awt.event.KeyEvent;
     9import java.awt.geom.Line2D;
     10import java.util.ArrayList;
     11import java.util.Collection;
     12import java.util.Comparator;
     13import java.util.LinkedHashSet;
     14import java.util.LinkedList;
     15import java.util.List;
     16import java.util.Set;
     17
     18import javax.swing.JOptionPane;
     19
     20import org.openstreetmap.josm.Main;
     21import org.openstreetmap.josm.command.AddCommand;
     22import org.openstreetmap.josm.command.ChangeCommand;
     23import org.openstreetmap.josm.command.Command;
     24import org.openstreetmap.josm.command.SequenceCommand;
     25import org.openstreetmap.josm.data.coor.EastNorth;
     26import org.openstreetmap.josm.data.coor.LatLon;
     27import org.openstreetmap.josm.data.osm.Node;
     28import org.openstreetmap.josm.data.osm.NodePositionComparator;
     29import org.openstreetmap.josm.data.osm.OsmPrimitive;
     30import org.openstreetmap.josm.data.osm.Way;
     31import org.openstreetmap.josm.tools.Shortcut;
     32
     33public class AddIntersectionsAction extends JosmAction {
     34    public AddIntersectionsAction() {
     35        super(tr("Add nodes at intersections"), "addintersect", tr("Add missing nodes at intersections of selected ways."),
     36                Shortcut.registerShortcut("tools:addintersect", tr("Tool: {0}", tr("Add nodes at intersections")), KeyEvent.VK_I, Shortcut.GROUP_EDIT), true);
     37        putValue("help", ht("/Action/AddIntersections"));
     38    }
     39    /**
     40     * Will find all intersection and add nodes there for list of given ways. Handles self-intersections too.
     41     * And make commands to add the intersection points to ways.
     42     * @param List<Way> - a list of ways to test
     43     * @return ArrayList<Node> List of new nodes
     44     * Prerequisite: no two nodes have the same coordinates.
     45     */
     46    public static ArrayList<Node> addIntersections(List<Way> ways, boolean test, List<Command> cmds) {
     47        //TODO: this is a bit slow - O( (number of nodes)^2 + numberOfIntersections * numberOfNodes )
     48
     49        //stupid java, cannot instantiate array of generic classes..
     50        @SuppressWarnings("unchecked")
     51        ArrayList<Node>[] newNodes = new ArrayList[ways.size()];
     52        boolean[] changedWays = new boolean[ways.size()];
     53
     54        Set<Node> intersectionNodes = new LinkedHashSet<Node>();
     55
     56        for (int pos = 0; pos < ways.size(); pos ++) {
     57            newNodes[pos] = new ArrayList<Node>(ways.get(pos).getNodes());
     58            changedWays[pos] = false;
     59        }
     60
     61        //iterate over all segment pairs and introduce the intersections
     62
     63        Comparator<Node> coordsComparator = new NodePositionComparator();
     64
     65        int seg1Way = 0;
     66        int seg1Pos = -1;
     67
     68        while (true) {
     69            //advance to next segment
     70            seg1Pos++;
     71            if (seg1Pos > newNodes[seg1Way].size() - 2) {
     72                seg1Way++;
     73                seg1Pos = 0;
     74
     75                if (seg1Way == ways.size()) { //finished
     76                    break;
     77                }
     78            }
     79
     80
     81            //iterate over secondary segment
     82
     83            int seg2Way = seg1Way;
     84            int seg2Pos = seg1Pos + 1;//skip the adjacent segment
     85
     86            while (true) {
     87
     88                //advance to next segment
     89                seg2Pos++;
     90                if (seg2Pos > newNodes[seg2Way].size() - 2) {
     91                    seg2Way++;
     92                    seg2Pos = 0;
     93
     94                    if (seg2Way == ways.size()) { //finished
     95                        break;
     96                    }
     97                }
     98
     99                //need to get them again every time, because other segments may be changed
     100                Node seg1Node1 = newNodes[seg1Way].get(seg1Pos);
     101                Node seg1Node2 = newNodes[seg1Way].get(seg1Pos + 1);
     102                Node seg2Node1 = newNodes[seg2Way].get(seg2Pos);
     103                Node seg2Node2 = newNodes[seg2Way].get(seg2Pos + 1);
     104
     105                int commonCount = 0;
     106                //test if we have common nodes to add.
     107                if (seg1Node1 == seg2Node1 || seg1Node1 == seg2Node2) {
     108                    commonCount ++;
     109
     110                    if (seg1Way == seg2Way &&
     111                            seg1Pos == 0 &&
     112                            seg2Pos == newNodes[seg2Way].size() -2) {
     113                        //do not add - this is first and last segment of the same way.
     114                    } else {
     115                        intersectionNodes.add(seg1Node1);
     116                    }
     117                }
     118
     119                if (seg1Node2 == seg2Node1 || seg1Node2 == seg2Node2) {
     120                    commonCount ++;
     121
     122                    intersectionNodes.add(seg1Node2);
     123                }
     124
     125                //no common nodes - find intersection
     126                if (commonCount == 0) {
     127                    LatLon intersection = getLineLineIntersection(
     128                            seg1Node1.getEastNorth().east(), seg1Node1.getEastNorth().north(),
     129                            seg1Node2.getEastNorth().east(), seg1Node2.getEastNorth().north(),
     130                            seg2Node1.getEastNorth().east(), seg2Node1.getEastNorth().north(),
     131                            seg2Node2.getEastNorth().east(), seg2Node2.getEastNorth().north());
     132
     133                    if (intersection != null) {
     134                        if (test) {
     135                            intersectionNodes.add(seg2Node1);
     136                            return new ArrayList<Node>(intersectionNodes);
     137                        }
     138
     139                        Node newNode = new Node(intersection);
     140                        Node intNode = newNode;
     141                        boolean insertInSeg1 = false;
     142                        boolean insertInSeg2 = false;
     143
     144                        //find if the intersection point is at end point of one of the segments, if so use that point
     145
     146                        //segment 1
     147                        if (coordsComparator.compare(newNode, seg1Node1) == 0) {
     148                            intNode = seg1Node1;
     149                        } else if (coordsComparator.compare(newNode, seg1Node2) == 0) {
     150                            intNode = seg1Node2;
     151                        } else {
     152                            insertInSeg1 = true;
     153                        }
     154
     155                        //segment 2
     156                        if (coordsComparator.compare(newNode, seg2Node1) == 0) {
     157                            intNode = seg2Node1;
     158                        } else if (coordsComparator.compare(newNode, seg2Node2) == 0) {
     159                            intNode = seg2Node2;
     160                        } else {
     161                            insertInSeg2 = true;
     162                        }
     163
     164                        if (insertInSeg1) {
     165                            newNodes[seg1Way].add(seg1Pos +1, intNode);
     166                            changedWays[seg1Way] = true;
     167
     168                            //fix seg2 position, as indexes have changed, seg2Pos is always bigger than seg1Pos on the same segment.
     169                            if (seg2Way == seg1Way) {
     170                                seg2Pos ++;
     171                            }
     172                        }
     173
     174                        if (insertInSeg2) {
     175                            newNodes[seg2Way].add(seg2Pos +1, intNode);
     176                            changedWays[seg2Way] = true;
     177
     178                            //Do not need to compare again to already split segment
     179                            seg2Pos ++;
     180                        }
     181
     182                        intersectionNodes.add(intNode);
     183
     184                        if (intNode == newNode) {
     185                            cmds.add(new AddCommand(intNode));
     186                        }
     187                    }
     188                }
     189                else if (test && intersectionNodes.size() > 0)
     190                    return new ArrayList<Node>(intersectionNodes);
     191            }
     192        }
     193
     194        for (int pos = 0; pos < ways.size(); pos ++) {
     195            if (changedWays[pos] == false) {
     196                continue;
     197            }
     198
     199            Way way = ways.get(pos);
     200            Way newWay = new Way(way);
     201            newWay.setNodes(newNodes[pos]);
     202
     203            cmds.add(new ChangeCommand(way, newWay));
     204        }
     205
     206        return new ArrayList<Node>(intersectionNodes);
     207    }
     208
     209
     210    /**
     211     * Finds the intersection of two lines
     212     * @return LatLon null if no intersection was found, the LatLon coordinates of the intersection otherwise
     213     */
     214    static private LatLon getLineLineIntersection(
     215            double x1, double y1, double x2, double y2,
     216            double x3, double y3, double x4, double y4) {
     217
     218        if (!Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x4, y4)) return null;
     219
     220        // Convert line from (point, point) form to ax+by=c
     221        double a1 = y2 - y1;
     222        double b1 = x1 - x2;
     223        double c1 = x2*y1 - x1*y2;
     224
     225        double a2 = y4 - y3;
     226        double b2 = x3 - x4;
     227        double c2 = x4*y3 - x3*y4;
     228
     229        // Solve the equations
     230        double det = a1*b2 - a2*b1;
     231        if (det == 0) return null; // Lines are parallel
     232
     233        return Main.proj.eastNorth2latlon(new EastNorth(
     234                (b1*c2 - b2*c1)/det,
     235                (a2*c1 -a1*c2)/det
     236        ));
     237    }
     238
     239    @Override
     240    public void actionPerformed(ActionEvent arg0) {
     241        if (!isEnabled())
     242            return;
     243        List<Way> ways = OsmPrimitive.getFilteredList(getCurrentDataSet().getSelected(), Way.class);
     244        if (ways.isEmpty()) {
     245            JOptionPane.showMessageDialog(
     246                    Main.parent,
     247                    tr("Please select one or more ways with intersections of segments."),
     248                    tr("Information"),
     249                    JOptionPane.INFORMATION_MESSAGE
     250            );
     251            return;
     252        }
     253
     254        LinkedList<Command> cmds = new LinkedList<Command>();
     255        addIntersections(ways, false, cmds);
     256        if (!cmds.isEmpty()) {
     257            Main.main.undoRedo.add(new SequenceCommand(tr("Add nodes at intersections"),cmds));
     258        }
     259    }
     260
     261    @Override
     262    protected void updateEnabledState() {
     263        if (getCurrentDataSet() == null) {
     264            setEnabled(false);
     265        } else {
     266            updateEnabledState(getCurrentDataSet().getSelected());
     267        }
     268    }
     269
     270    @Override
     271    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
     272        setEnabled(selection != null && !selection.isEmpty());
     273    }
     274}
  • src/org/openstreetmap/josm/actions/JoinAreasAction.java

     
    11// License: GPL. Copyright 2007 by Immanuel Scholz and others
    22package org.openstreetmap.josm.actions;
    33
     4import static org.openstreetmap.josm.actions.AddIntersectionsAction.addIntersections;
    45import static org.openstreetmap.josm.gui.conflict.tags.TagConflictResolutionUtil.combineTigerTags;
    56import static org.openstreetmap.josm.gui.conflict.tags.TagConflictResolutionUtil.completeTagCollectionForEditing;
    67import static org.openstreetmap.josm.gui.conflict.tags.TagConflictResolutionUtil.normalizeTagCollectionBeforeEditing;
     
    1112import java.awt.event.ActionEvent;
    1213import java.awt.event.KeyEvent;
    1314import java.awt.geom.Area;
    14 import java.awt.geom.Line2D;
    1515import java.util.ArrayList;
    1616import java.util.Collection;
    1717import java.util.Collections;
    18 import java.util.Comparator;
    1918import java.util.HashMap;
    2019import java.util.HashSet;
    2120import java.util.LinkedHashSet;
     
    3837import org.openstreetmap.josm.corrector.UserCancelException;
    3938import org.openstreetmap.josm.data.UndoRedoHandler;
    4039import org.openstreetmap.josm.data.coor.EastNorth;
    41 import org.openstreetmap.josm.data.coor.LatLon;
    4240import org.openstreetmap.josm.data.osm.DataSet;
    4341import org.openstreetmap.josm.data.osm.Node;
     42import org.openstreetmap.josm.data.osm.NodePositionComparator;
    4443import org.openstreetmap.josm.data.osm.OsmPrimitive;
    4544import org.openstreetmap.josm.data.osm.Relation;
    4645import org.openstreetmap.josm.data.osm.RelationMember;
     
    289288        }
    290289    }
    291290
    292     /**
    293      * Provides some node order , based on coordinates, nodes with equal coordinates are equal.
    294      * @author viesturs
    295      *
    296      */
    297     private class NodePositionComparator implements Comparator<Node> {
    298291
    299         @Override
    300         public int compare(Node n1, Node n2) {
    301 
    302             double dLat = n1.getCoor().lat() - n2.getCoor().lat();
    303             double dLon = n1.getCoor().lon() - n2.getCoor().lon();
    304 
    305             if (dLat > 0)
    306                 return 1;
    307             else if (dLat < 0)
    308                 return -1;
    309             else if (dLon == 0) //dlat is 0 here
    310                 return 0;
    311             else
    312                 return dLon > 0 ? 1 : -1;
    313         }
    314     }
    315 
    316 
    317292    /**
    318293     * Helper storage class for finding findOuterWays
    319294     * @author viesturs
     
    429404        }
    430405
    431406        //find intersection points
    432         ArrayList<Node> nodes = addIntersections(allStartingWays, true);
     407        ArrayList<Node> nodes = addIntersections(allStartingWays, true, cmds);
    433408        return nodes.size() > 0;
    434409    }
    435410
     
    465440        }
    466441
    467442        //find intersection points
    468         ArrayList<Node> nodes = addIntersections(allStartingWays, false);
     443        ArrayList<Node> nodes = addIntersections(allStartingWays, false, cmds);
    469444
    470445        //no intersections, return.
    471446        if (nodes.size() == 0) return result;
     
    660635    }
    661636
    662637
    663 
    664638    /**
    665      * Will find all intersection and add nodes there for list of given ways. Handles self-intersections too.
    666      * And make commands to add the intersection points to ways.
    667      * @param List<Way> - a list of ways to test
    668      * @return ArrayList<Node> List of new nodes
    669      * Prerequisite: no two nodes have the same coordinates.
    670      */
    671     private ArrayList<Node> addIntersections(List<Way> ways, boolean test) {
    672         //TODO: this is a bit slow - O( (number of nodes)^2 + numberOfIntersections * numberOfNodes )
    673 
    674         //stupid java, cannot instantiate array of generic classes..
    675         @SuppressWarnings("unchecked")
    676         ArrayList<Node>[] newNodes = new ArrayList[ways.size()];
    677         boolean[] changedWays = new boolean[ways.size()];
    678 
    679         Set<Node> intersectionNodes = new LinkedHashSet<Node>();
    680 
    681         for (int pos = 0; pos < ways.size(); pos ++) {
    682             newNodes[pos] = new ArrayList<Node>(ways.get(pos).getNodes());
    683             changedWays[pos] = false;
    684         }
    685 
    686         //iterate over all segment pairs and introduce the intersections
    687 
    688         Comparator<Node> coordsComparator = new NodePositionComparator();
    689 
    690         int seg1Way = 0;
    691         int seg1Pos = -1;
    692 
    693         while (true) {
    694             //advance to next segment
    695             seg1Pos++;
    696             if (seg1Pos > newNodes[seg1Way].size() - 2) {
    697                 seg1Way++;
    698                 seg1Pos = 0;
    699 
    700                 if (seg1Way == ways.size()) { //finished
    701                     break;
    702                 }
    703             }
    704 
    705 
    706             //iterate over secondary segment
    707 
    708             int seg2Way = seg1Way;
    709             int seg2Pos = seg1Pos + 1;//skip the adjacent segment
    710 
    711             while (true) {
    712 
    713                 //advance to next segment
    714                 seg2Pos++;
    715                 if (seg2Pos > newNodes[seg2Way].size() - 2) {
    716                     seg2Way++;
    717                     seg2Pos = 0;
    718 
    719                     if (seg2Way == ways.size()) { //finished
    720                         break;
    721                     }
    722                 }
    723 
    724                 //need to get them again every time, because other segments may be changed
    725                 Node seg1Node1 = newNodes[seg1Way].get(seg1Pos);
    726                 Node seg1Node2 = newNodes[seg1Way].get(seg1Pos + 1);
    727                 Node seg2Node1 = newNodes[seg2Way].get(seg2Pos);
    728                 Node seg2Node2 = newNodes[seg2Way].get(seg2Pos + 1);
    729 
    730                 int commonCount = 0;
    731                 //test if we have common nodes to add.
    732                 if (seg1Node1 == seg2Node1 || seg1Node1 == seg2Node2) {
    733                     commonCount ++;
    734 
    735                     if (seg1Way == seg2Way &&
    736                             seg1Pos == 0 &&
    737                             seg2Pos == newNodes[seg2Way].size() -2) {
    738                         //do not add - this is first and last segment of the same way.
    739                     } else {
    740                         intersectionNodes.add(seg1Node1);
    741                     }
    742                 }
    743 
    744                 if (seg1Node2 == seg2Node1 || seg1Node2 == seg2Node2) {
    745                     commonCount ++;
    746 
    747                     intersectionNodes.add(seg1Node2);
    748                 }
    749 
    750                 //no common nodes - find intersection
    751                 if (commonCount == 0) {
    752                     LatLon intersection = getLineLineIntersection(
    753                             seg1Node1.getEastNorth().east(), seg1Node1.getEastNorth().north(),
    754                             seg1Node2.getEastNorth().east(), seg1Node2.getEastNorth().north(),
    755                             seg2Node1.getEastNorth().east(), seg2Node1.getEastNorth().north(),
    756                             seg2Node2.getEastNorth().east(), seg2Node2.getEastNorth().north());
    757 
    758                     if (intersection != null) {
    759                         if (test) {
    760                             intersectionNodes.add(seg2Node1);
    761                             return new ArrayList<Node>(intersectionNodes);
    762                         }
    763 
    764                         Node newNode = new Node(intersection);
    765                         Node intNode = newNode;
    766                         boolean insertInSeg1 = false;
    767                         boolean insertInSeg2 = false;
    768 
    769                         //find if the intersection point is at end point of one of the segments, if so use that point
    770 
    771                         //segment 1
    772                         if (coordsComparator.compare(newNode, seg1Node1) == 0) {
    773                             intNode = seg1Node1;
    774                         } else if (coordsComparator.compare(newNode, seg1Node2) == 0) {
    775                             intNode = seg1Node2;
    776                         } else {
    777                             insertInSeg1 = true;
    778                         }
    779 
    780                         //segment 2
    781                         if (coordsComparator.compare(newNode, seg2Node1) == 0) {
    782                             intNode = seg2Node1;
    783                         } else if (coordsComparator.compare(newNode, seg2Node2) == 0) {
    784                             intNode = seg2Node2;
    785                         } else {
    786                             insertInSeg2 = true;
    787                         }
    788 
    789                         if (insertInSeg1) {
    790                             newNodes[seg1Way].add(seg1Pos +1, intNode);
    791                             changedWays[seg1Way] = true;
    792 
    793                             //fix seg2 position, as indexes have changed, seg2Pos is always bigger than seg1Pos on the same segment.
    794                             if (seg2Way == seg1Way) {
    795                                 seg2Pos ++;
    796                             }
    797                         }
    798 
    799                         if (insertInSeg2) {
    800                             newNodes[seg2Way].add(seg2Pos +1, intNode);
    801                             changedWays[seg2Way] = true;
    802 
    803                             //Do not need to compare again to already split segment
    804                             seg2Pos ++;
    805                         }
    806 
    807                         intersectionNodes.add(intNode);
    808 
    809                         if (intNode == newNode) {
    810                             cmds.add(new AddCommand(intNode));
    811                         }
    812                     }
    813                 }
    814                 else if (test && intersectionNodes.size() > 0)
    815                     return new ArrayList<Node>(intersectionNodes);
    816             }
    817         }
    818 
    819         for (int pos = 0; pos < ways.size(); pos ++) {
    820             if (changedWays[pos] == false) {
    821                 continue;
    822             }
    823 
    824             Way way = ways.get(pos);
    825             Way newWay = new Way(way);
    826             newWay.setNodes(newNodes[pos]);
    827 
    828             cmds.add(new ChangeCommand(way, newWay));
    829         }
    830 
    831         return new ArrayList<Node>(intersectionNodes);
    832     }
    833 
    834     /**
    835      * Finds the intersection of two lines
    836      * @return LatLon null if no intersection was found, the LatLon coordinates of the intersection otherwise
    837      */
    838     static private LatLon getLineLineIntersection(
    839             double x1, double y1, double x2, double y2,
    840             double x3, double y3, double x4, double y4) {
    841 
    842         if (!Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x4, y4)) return null;
    843 
    844         // Convert line from (point, point) form to ax+by=c
    845         double a1 = y2 - y1;
    846         double b1 = x1 - x2;
    847         double c1 = x2*y1 - x1*y2;
    848 
    849         double a2 = y4 - y3;
    850         double b2 = x3 - x4;
    851         double c2 = x4*y3 - x3*y4;
    852 
    853         // Solve the equations
    854         double det = a1*b2 - a2*b1;
    855         if (det == 0) return null; // Lines are parallel
    856 
    857         return Main.proj.eastNorth2latlon(new EastNorth(
    858                 (b1*c2 - b2*c1)/det,
    859                 (a2*c1 -a1*c2)/det
    860         ));
    861     }
    862 
    863 
    864 
    865     /**
    866639     * Commits the command list with a description
    867640     * @param String The description of what the commands do
    868641     */
  • src/org/openstreetmap/josm/gui/MainMenu.java

     
    1616
    1717import org.openstreetmap.josm.Main;
    1818import org.openstreetmap.josm.actions.AboutAction;
     19import org.openstreetmap.josm.actions.AddIntersectionsAction;
    1920import org.openstreetmap.josm.actions.AddNodeAction;
    2021import org.openstreetmap.josm.actions.AlignInCircleAction;
    2122import org.openstreetmap.josm.actions.AlignInLineAction;
     
    5152import org.openstreetmap.josm.actions.OpenFileAction;
    5253import org.openstreetmap.josm.actions.OpenLocationAction;
    5354import org.openstreetmap.josm.actions.OrthogonalizeAction;
     55import org.openstreetmap.josm.actions.OrthogonalizeAction.Undo;
    5456import org.openstreetmap.josm.actions.PasteAction;
    5557import org.openstreetmap.josm.actions.PasteTagsAction;
    5658import org.openstreetmap.josm.actions.PreferencesAction;
     
    7577import org.openstreetmap.josm.actions.WireframeToggleAction;
    7678import org.openstreetmap.josm.actions.ZoomInAction;
    7779import org.openstreetmap.josm.actions.ZoomOutAction;
    78 import org.openstreetmap.josm.actions.OrthogonalizeAction.Undo;
    7980import org.openstreetmap.josm.actions.audio.AudioBackAction;
    8081import org.openstreetmap.josm.actions.audio.AudioFasterAction;
    8182import org.openstreetmap.josm.actions.audio.AudioFwdAction;
     
    152153    public final JosmAction joinNodeWay = new JoinNodeWayAction();
    153154    public final JosmAction unglueNodes = new UnGlueAction();
    154155    public final JosmAction simplifyWay = new SimplifyWayAction();
     156    public final JosmAction addIntersections = new AddIntersectionsAction();
    155157    public final JosmAction joinAreas = new JoinAreasAction();
    156158    public final InfoAction info = new InfoAction();
    157159    public final HistoryInfoAction historyinfo = new HistoryInfoAction();
     
    315317        add(toolsMenu, mergeNodes);
    316318        add(toolsMenu, joinNodeWay);
    317319        add(toolsMenu, unglueNodes);
     320        add(toolsMenu, addIntersections);
    318321        add(toolsMenu, joinAreas);
    319322        toolsMenu.addSeparator();
    320323        add(toolsMenu, info);
  • src/org/openstreetmap/josm/data/osm/NodePositionComparator.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.osm;
     3
     4import java.util.Comparator;
     5
     6/**
     7 * Provides some node order , based on coordinates, nodes with equal coordinates are equal.
     8 * @author viesturs
     9 *
     10 */
     11public class NodePositionComparator implements Comparator<Node> {
     12
     13    @Override
     14    public int compare(Node n1, Node n2) {
     15
     16        double dLat = n1.getCoor().lat() - n2.getCoor().lat();
     17        double dLon = n1.getCoor().lon() - n2.getCoor().lon();
     18
     19        if (dLat > 0)
     20            return 1;
     21        else if (dLat < 0)
     22            return -1;
     23        else if (dLon == 0) //dlat is 0 here
     24            return 0;
     25        else
     26            return dLon > 0 ? 1 : -1;
     27    }
     28}