Ignore:
Timestamp:
2018-01-22T23:56:24+01:00 (7 years ago)
Author:
donvip
Message:

fix #josm15802 - Circular Building Tool (patch by abalosc1, Digital Globe)

Location:
applications/editors/josm/plugins/buildings_tools/src/buildings_tools
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/buildings_tools/src/buildings_tools/Building.java

    r33735 r34026  
    99import java.awt.Point;
    1010import java.awt.geom.GeneralPath;
     11import java.util.ArrayList;
    1112import java.util.Collection;
     13import java.util.Collections;
    1214import java.util.LinkedList;
    1315import java.util.List;
     
    1719
    1820import org.openstreetmap.josm.Main;
     21import org.openstreetmap.josm.actions.CreateCircleAction;
    1922import org.openstreetmap.josm.command.AddCommand;
    2023import org.openstreetmap.josm.command.ChangeCommand;
     
    7174
    7275    public boolean isRectDrawing() {
    73         return drawingAngle != null && ToolSettings.getWidth() == 0 && ToolSettings.getLenStep() == 0;
     76        return drawingAngle != null && ToolSettings.getWidth() == 0 && ToolSettings.getLenStep() == 0
     77                && ToolSettings.Shape.RECTANGLE.equals(ToolSettings.getShape());
    7478    }
    7579
     
    131135        final EastNorth p1 = en[0];
    132136        en[1] = new EastNorth(p1.east() + Math.sin(heading) * len * meter, p1.north() + Math.cos(heading) * len * meter);
    133         en[2] = new EastNorth(p1.east() + Math.sin(heading) * len * meter + Math.cos(heading) * width * meter,
    134                 p1.north() + Math.cos(heading) * len * meter - Math.sin(heading) * width * meter);
    135         en[3] = new EastNorth(p1.east() + Math.cos(heading) * width * meter,
    136                 p1.north() - Math.sin(heading) * width * meter);
     137        if (ToolSettings.Shape.RECTANGLE.equals(ToolSettings.getShape())) {
     138            en[2] = new EastNorth(p1.east() + Math.sin(heading) * len * meter + Math.cos(heading) * width * meter,
     139                    p1.north() + Math.cos(heading) * len * meter - Math.sin(heading) * width * meter);
     140            en[3] = new EastNorth(p1.east() + Math.cos(heading) * width * meter,
     141                    p1.north() - Math.sin(heading) * width * meter);
     142        }
    137143    }
    138144
     
    173179    }
    174180
     181    public void setPlaceCircle(EastNorth p2, double width, boolean ignoreConstraints) {
     182        if (en[0] == null)
     183            throw new IllegalStateException("setPlace() called without the base point");
     184        this.heading = en[0].heading(p2);
     185        if (!ignoreConstraints)
     186            this.heading = angleSnap.snapAngle(this.heading);
     187        this.len = width;
     188
     189        updatePos();
     190    }
     191
    175192    public void setPlaceRect(EastNorth p2) {
    176193        if (en[0] == null)
     
    199216        Point pp1 = mv.getPoint(eastNorth2latlon(en[0]));
    200217        Point pp2 = mv.getPoint(eastNorth2latlon(en[1]));
    201         Point pp3 = mv.getPoint(eastNorth2latlon(en[2]));
    202         Point pp4 = mv.getPoint(eastNorth2latlon(en[3]));
    203 
    204218        b.moveTo(pp1.x, pp1.y);
    205219        b.lineTo(pp2.x, pp2.y);
    206         b.lineTo(pp3.x, pp3.y);
    207         b.lineTo(pp4.x, pp4.y);
     220        if (ToolSettings.Shape.RECTANGLE.equals(ToolSettings.getShape())) {
     221            Point pp3 = mv.getPoint(eastNorth2latlon(en[2]));
     222            Point pp4 = mv.getPoint(eastNorth2latlon(en[3]));
     223            b.lineTo(pp3.x, pp3.y);
     224            b.lineTo(pp4.x, pp4.y);
     225        }
    208226        b.lineTo(pp1.x, pp1.y);
    209227        g.draw(b);
     
    234252    private Node getAddressNode() {
    235253        BBox bbox = new BBox(eastNorth2latlon(en[0]), eastNorth2latlon(en[1]));
    236         bbox.add(eastNorth2latlon(en[2]));
    237         bbox.add(eastNorth2latlon(en[3]));
     254        if (ToolSettings.Shape.RECTANGLE.equals(ToolSettings.getShape())) {
     255            bbox.add(eastNorth2latlon(en[2]));
     256            bbox.add(eastNorth2latlon(en[3]));
     257        }
    238258        List<Node> nodes = new LinkedList<>();
    239259        nodesloop:
     
    266286    }
    267287
    268     public Way create() {
     288    public Way createCircle() {
     289        DataSet ds = MainApplication.getLayerManager().getEditDataSet();
     290        Collection<OsmPrimitive> selectedPrimitives = ds.getAllSelected();
     291        ds.clearSelection();
     292
     293        if (len == 0)
     294            return null;
     295        final boolean[] created = new boolean[2];
     296        final Node[] nodes = new Node[2];
     297        for (int i = 0; i < 2; i++) {
     298
     299            Node n = findNode(en[i]);
     300            if (n == null) {
     301                nodes[i] = new Node(eastNorth2latlon(en[i]));
     302                created[i] = true;
     303            } else {
     304                nodes[i] = n;
     305                created[i] = false;
     306            }
     307            if (nodes[i].getCoor().isOutSideWorld()) {
     308                JOptionPane.showMessageDialog(Main.parent,
     309                        tr("Cannot place building outside of the world."));
     310                return null;
     311            }
     312        }
     313        Way w = new Way();
     314        w.addNode(nodes[0]);
     315        w.addNode(nodes[1]);
     316
     317        Collection<Command> addNodesCmd = new LinkedList<>();
     318
     319        for (int i = 0; i < 2; i++) {
     320            if (created[i]) {
     321                AddCommand addNode = new AddCommand(ds, nodes[i]);
     322                addNodesCmd.add(addNode);
     323            }
     324        }
     325
     326        if (addNodesCmd.size() > 0) {
     327            Command addNodes = new SequenceCommand(tr("Add nodes for building"), addNodesCmd);
     328            Main.main.undoRedo.add(addNodes);
     329        }
     330
     331        // Nodes must be selected for create circle action
     332        for (int i = 0; i < 2; i++) {
     333            if (created[i]) {
     334                ds.addSelected(nodes[i]);
     335            }
     336        }
     337
     338        CreateCircleAction action = new CreateCircleAction();
     339        action.setEnabled(true);
     340        action.actionPerformed(null);
     341
     342        ds.clearSelection();
     343        ds.addSelected(selectedPrimitives);
     344
     345        // get the way with the smallest id with the assumption that it is
     346        // newest way created by CreateCirclAction
     347        List<Way> ways = new ArrayList<>(ds.getWays());
     348        Collections.sort(ways);
     349        w = ways.get(0);
     350
     351        addAddress(w);
     352
     353        return w;
     354    }
     355
     356    public Way createRectangle() {
    269357        if (len == 0)
    270358            return null;
     
    307395        cmds.add(new AddCommand(ds, w));
    308396
     397        addAddress(w);
     398
     399        Command c = new SequenceCommand(tr("Create building"), cmds);
     400        Main.main.undoRedo.add(c);
     401        return w;
     402    }
     403
     404    private void addAddress(Way w) {
    309405        if (ToolSettings.PROP_USE_ADDR_NODE.get()) {
    310406            Node addrNode = getAddressNode();
    311407            if (addrNode != null) {
     408                Collection<Command> addressCmds = new LinkedList<>();
    312409                for (Entry<String, String> entry : addrNode.getKeys().entrySet()) {
    313410                    w.put(entry.getKey(), entry.getValue());
     
    323420                        }
    324421                    }
    325                     cmds.add(new ChangeCommand(r, rnew));
     422                    addressCmds.add(new ChangeCommand(r, rnew));
    326423                }
    327                 cmds.add(new DeleteCommand(addrNode));
    328             }
    329         }
    330         Command c = new SequenceCommand(tr("Create building"), cmds);
    331         Main.main.undoRedo.add(c);
    332         return w;
     424                addressCmds.add(new DeleteCommand(addrNode));
     425                Command c = new SequenceCommand(tr("Add address for building"), addressCmds);
     426                Main.main.undoRedo.add(c);
     427            }
     428        }
    333429    }
    334430}
  • applications/editors/josm/plugins/buildings_tools/src/buildings_tools/BuildingSizeDialog.java

    r30045 r34026  
    99import java.text.ParseException;
    1010
     11import javax.swing.ButtonGroup;
    1112import javax.swing.JButton;
    1213import javax.swing.JCheckBox;
    1314import javax.swing.JFormattedTextField;
     15import javax.swing.JRadioButton;
    1416
    1517import org.openstreetmap.josm.tools.GBC;
     
    2224    private final JCheckBox cAutoSelect = new JCheckBox(tr("Auto-select building"));
    2325    private final JCheckBox cAddrNode = new JCheckBox(tr("Use address nodes under buildings"));
     26    private final JRadioButton circleRadio = new JRadioButton(tr("Circle"));
     27    private final JRadioButton rectangleRadio = new JRadioButton(tr("Rectangle"));
    2428
    2529    public BuildingSizeDialog() {
    26         super(tr("Set buildings size"));
     30        super(tr("Set buildings size and shape"));
    2731
    28         addLabelled(tr("Buildings width:"), twidth);
     32        ButtonGroup shapeGroup = new ButtonGroup();
     33        shapeGroup.add(circleRadio);
     34        shapeGroup.add(rectangleRadio);
     35        circleRadio.setSelected(ToolSettings.Shape.CIRCLE.equals(ToolSettings.getShape()));
     36        rectangleRadio.setSelected(ToolSettings.Shape.RECTANGLE.equals(ToolSettings.getShape()));
     37
     38        panel.add(rectangleRadio, GBC.eol().fill(GBC.HORIZONTAL));
     39        panel.add(circleRadio, GBC.eol().fill(GBC.HORIZONTAL));
     40
     41        addLabelled(tr("Buildings width/diameter:"), twidth);
    2942        addLabelled(tr("Length step:"), tlenstep);
    3043        panel.add(caddr, GBC.eol().fill(GBC.HORIZONTAL));
     
    7588
    7689    public final void saveSettings() {
     90        if (circleRadio.isSelected()) {
     91            ToolSettings.saveShape(ToolSettings.Shape.CIRCLE);
     92        } else if (rectangleRadio.isSelected()) {
     93            ToolSettings.saveShape(ToolSettings.Shape.RECTANGLE);
     94        }
    7795        ToolSettings.setSizes(width(), lenstep());
    7896        ToolSettings.setAddrDialog(useAddr());
  • applications/editors/josm/plugins/buildings_tools/src/buildings_tools/BuildingsToolsPlugin.java

    r33735 r34026  
    3030        JMenu dataMenu = MainApplication.getMenu().dataMenu;
    3131        MainMenu.add(dataMenu, new BuildingSizeAction());
     32        MainMenu.add(dataMenu, new BuildingCircleAction());
     33        MainMenu.add(dataMenu, new BuildingRectangleAction());
    3234        MainMenu.add(dataMenu, new MergeAddrPointsAction());
    3335    }
  • applications/editors/josm/plugins/buildings_tools/src/buildings_tools/DrawBuildingAction.java

    r33735 r34026  
    7878    private static Cursor getCursor() {
    7979        try {
    80             return ImageProvider.getCursor("crosshair", "building");
     80            if (ToolSettings.Shape.CIRCLE.equals(ToolSettings.getShape())) {
     81                return ImageProvider.getCursor("crosshair", "silo");
     82            } else {
     83                return ImageProvider.getCursor("crosshair", "building");
     84            }
    8185        } catch (Exception e) {
    8286            Logging.error(e);
     
    212216
    213217    private boolean isRectDrawing() {
    214         return building.isRectDrawing() && (!shift || ToolSettings.isBBMode());
     218        return building.isRectDrawing() && (!shift || ToolSettings.isBBMode())
     219                && ToolSettings.Shape.RECTANGLE.equals(ToolSettings.getShape());
    215220    }
    216221
     
    218223        EastNorth p = getEastNorth();
    219224        if (isRectDrawing()) {
    220             building.setPlaceRect(p);
    221             return shift ? Mode.DrawingAngFix : Mode.None;
     225                building.setPlaceRect(p);
     226                return shift ? Mode.DrawingAngFix : Mode.None;
     227        } else if (ToolSettings.Shape.CIRCLE.equals(ToolSettings.getShape())) {
     228            if (ToolSettings.getWidth() != 0) {
     229                building.setPlaceCircle(p, ToolSettings.getWidth(), shift);
     230            } else {
     231                building.setPlace(p, ToolSettings.getWidth(), ToolSettings.getLenStep(), shift);
     232            }
     233            MainApplication.getMap().statusLine.setDist(building.getLength());
     234            this.nextMode = Mode.None;
     235            return this.nextMode;
    222236        } else {
    223237            building.setPlace(p, ToolSettings.getWidth(), ToolSettings.getLenStep(), shift);
     
    278292        mousePos = e.getPoint();
    279293        drawStartPos = mousePos;
    280 
    281         Node n = MainApplication.getMap().mapView.getNearestNode(mousePos, OsmPrimitive::isUsable);
    282         if (n == null) {
     294        if (ToolSettings.Shape.CIRCLE.equals(ToolSettings.getShape())) {
    283295            building.setBase(latlon2eastNorth(MainApplication.getMap().mapView.getLatLon(mousePos.x, mousePos.y)));
    284296        } else {
    285             building.setBase(n);
     297            Node n = MainApplication.getMap().mapView.getNearestNode(mousePos, OsmPrimitive::isUsable);
     298            if (n == null) {
     299                building.setBase(latlon2eastNorth(MainApplication.getMap().mapView.getLatLon(mousePos.x, mousePos.y)));
     300            } else {
     301                building.setBase(n);
     302            }
    286303        }
    287304        mode = Mode.Drawing;
     
    301318    private void drawingFinish() {
    302319        if (building.getLength() != 0) {
    303             Way w = building.create();
     320            Way w;
     321            if (ToolSettings.Shape.CIRCLE.equals(ToolSettings.getShape())) {
     322                w = building.createCircle();
     323            } else {
     324                w = building.createRectangle();
     325            }
    304326            if (w != null) {
    305327                if (!alt || ToolSettings.isUsingAddr())
     
    372394                setCursor(customCursor);
    373395            else
    374                 setCursor(cursorCrosshair);
     396                setCursor(getCursor());
    375397        }
    376398
  • applications/editors/josm/plugins/buildings_tools/src/buildings_tools/ToolSettings.java

    r33735 r34026  
    2222
    2323    public static final BooleanProperty PROP_USE_ADDR_NODE = new BooleanProperty("buildings_tools.addrNode", false);
     24
     25    public enum Shape {
     26            CIRCLE, RECTANGLE
     27    }
     28
     29    private static Shape shape = loadShape();
    2430    private static double width = 0;
    2531    private static double lenstep = 0;
     
    2733    private static final Map<String, String> TAGS = new HashMap<>();
    2834    private static boolean autoSelect;
     35
     36    public static Shape getShape() {
     37        loadShape();
     38        return shape;
     39    }
    2940
    3041    public static void setAddrDialog(boolean _useAddr) {
     
    7889    }
    7990
     91    public static void saveShape(Shape shape) {
     92        Main.pref.put("buildings_tool.shape", shape.name());
     93    }
     94
     95    private static Shape loadShape() {
     96        String shape = Main.pref.get("buildings_tool.shape");
     97        if (ToolSettings.Shape.CIRCLE.name().equals(shape)) {
     98            ToolSettings.shape = Shape.CIRCLE;
     99            return Shape.CIRCLE;
     100        } else {
     101            ToolSettings.shape = Shape.RECTANGLE;
     102            return (Shape.RECTANGLE);
     103        }
     104    }
     105
    80106    public static void setBBMode(boolean bbmode) {
    81107        Main.pref.putBoolean("buildings_tools.bbmode", bbmode);
Note: See TracChangeset for help on using the changeset viewer.