Changeset 9077 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2015-12-01T15:50:50+01:00 (8 years ago)
Author:
bastiK
Message:

mapcss: partial fill - fix linecap (see #12104)

Location:
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java

    r9076 r9077  
    469469     * far to fill from the boundary towards the center of the area;
    470470     * if null, area will be filled completely
     471     * @param pfClip clipping area for partial fill
    471472     * @param unclosedHighlight true, if the fact that the way / multipolygon is not
    472473     * properly closed should be highlighted; this parameter is only used
     
    475476     * @param text The text to write on the area.
    476477     */
    477     protected void drawArea(OsmPrimitive osm, Path2D.Double path, Color color, MapImage fillImage, Float extent, boolean unclosedHighlight,
     478    protected void drawArea(OsmPrimitive osm, Path2D.Double path, Color color, MapImage fillImage, Float extent, Path2D.Double pfClip, boolean unclosedHighlight,
    478479            boolean disabled, TextElement text) {
    479480
     
    495496                        g.draw(area);
    496497                    } else {
    497                         Shape clip = g.getClip();
    498                         g.clip(area);
     498                        Shape oldClip = g.getClip();
     499                        Shape clip = area;
     500                        if (pfClip != null) {
     501                            clip = pfClip.createTransformedShape(nc.getAffineTransform());
     502                        }
     503                        g.clip(clip);
    499504                        g.setStroke(new BasicStroke(2 * extent, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
    500505                        g.draw(area);
    501                         g.setClip(clip);
     506                        g.setClip(oldClip);
    502507                    }
    503508                }
     
    518523                        g.draw(area);
    519524                    } else {
    520                         Shape clip = g.getClip();
     525                        Shape oldClip = g.getClip();
    521526                        BasicStroke stroke = new BasicStroke(2 * extent, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);
    522527                        g.clip(stroke.createStrokedShape(area));
    523                         g.fill(area);
    524                         g.setClip(clip);
     528                        Shape fill = area;
     529                        if (pfClip != null) {
     530                            fill = pfClip.createTransformedShape(nc.getAffineTransform());
     531                        }
     532                        g.fill(fill);
     533                        g.setClip(oldClip);
    525534                    }
    526535                }
     
    623632            for (PolyData pd : multipolygon.getCombinedPolygons()) {
    624633                Path2D.Double p = pd.get();
     634                Path2D.Double pfClip = null;
    625635                if (!isAreaVisible(p)) {
    626636                    continue;
     
    637647                    } else {
    638648                        unclosedHighlight = isUnclosedAreaHighlight;
     649                        pfClip = getPFClip(pd, extent * scale);
    639650                    }
    640651                }
    641652                drawArea(r, p,
    642653                        pd.selected ? paintSettings.getRelationSelectedColor(color.getAlpha()) : color,
    643                         fillImage, extent, unclosedHighlight, disabled, text);
     654                        fillImage, extent, pfClip, unclosedHighlight, disabled, text);
    644655            }
    645656        }
     
    658669     */
    659670    public void drawArea(Way w, Color color, MapImage fillImage, Float extent, boolean disabled, TextElement text) {
    660         if (extent != null && w.isClosed()) {
    661             AreaAndPerimeter ap = Geometry.getAreaAndPerimeter(w.getNodes());
    662             // if partial fill would only leave a small gap in the center ...
    663             if (ap.getPerimeter() * extent * scale > partialFillThreshold / 100 * ap.getArea()) {
    664                 // ... turn it off and fill completely
    665                 extent = null;
    666             }
    667         }
    668         drawArea(w, getPath(w), color, fillImage, extent, isUnclosedAreaHighlight && !w.isClosed(), disabled, text);
     671        Path2D.Double pfClip = null;
     672        if (extent != null) {
     673            if (w.isClosed()) {
     674                AreaAndPerimeter ap = Geometry.getAreaAndPerimeter(w.getNodes());
     675                // if partial fill would only leave a small gap in the center ...
     676                if (ap.getPerimeter() * extent * scale > partialFillThreshold / 100 * ap.getArea()) {
     677                    // ... turn it off and fill completely
     678                    extent = null;
     679                }
     680            } else {
     681                pfClip = getPFClip(w, extent * scale);
     682            }
     683        }
     684        drawArea(w, getPath(w), color, fillImage, extent, pfClip, isUnclosedAreaHighlight && !w.isClosed(), disabled, text);
    669685    }
    670686
     
    15851601    }
    15861602
     1603    private static Path2D.Double getPFClip(Way w, double extent) {
     1604        Path2D.Double clip = new Path2D.Double();
     1605        buildPFClip(clip, w.getNodes(), extent);
     1606        return clip;
     1607    }
     1608
     1609    private static Path2D.Double getPFClip(PolyData pd, double extent) {
     1610        Path2D.Double clip = new Path2D.Double();
     1611        clip.setWindingRule(Path2D.WIND_EVEN_ODD);
     1612        buildPFClip(clip, pd.getNodes(), extent);
     1613        for (PolyData pdInner : pd.getInners()) {
     1614            buildPFClip(clip, pdInner.getNodes(), extent);
     1615        }
     1616        return clip;
     1617    }
     1618
     1619    private static void buildPFClip(Path2D.Double clip, List<Node> nodes, double extent) {
     1620        boolean initial = true;
     1621        for (Node n : nodes) {
     1622            EastNorth p = n.getEastNorth();
     1623            if (p != null) {
     1624                if (initial) {
     1625                    clip.moveTo(p.getX(), p.getY());
     1626                    initial = false;
     1627                } else {
     1628                    clip.lineTo(p.getX(), p.getY());
     1629                }
     1630            }
     1631        }
     1632        if (nodes.size() >= 3) {
     1633            EastNorth fst = nodes.get(0).getEastNorth();
     1634            EastNorth snd = nodes.get(1).getEastNorth();
     1635            EastNorth lst = nodes.get(nodes.size() - 1).getEastNorth();
     1636            EastNorth lbo = nodes.get(nodes.size() - 2).getEastNorth();
     1637
     1638            EastNorth cLst = getPFDisplacedEndPoint(lbo, lst, fst, extent);
     1639            EastNorth cFst = getPFDisplacedEndPoint(snd, fst, cLst != null ? cLst : lst, extent);
     1640            if (cLst == null && cFst != null) {
     1641                cLst = getPFDisplacedEndPoint(lbo, lst, cFst, extent);
     1642            }
     1643            if (cLst != null) {
     1644                clip.lineTo(cLst.getX(), cLst.getY());
     1645            }
     1646            if (cFst != null) {
     1647                clip.lineTo(cFst.getX(), cFst.getY());
     1648            }
     1649        }
     1650    }
     1651
     1652    private static EastNorth getPFDisplacedEndPoint(EastNorth p1, EastNorth p2, EastNorth p3, double extent) {
     1653        double dx1 = p2.getX() - p1.getX();
     1654        double dy1 = p2.getY() - p1.getY();
     1655        double dx2 = p3.getX() - p2.getX();
     1656        double dy2 = p3.getY() - p2.getY();
     1657        if (dx1 * dx2 + dy1 * dy2 < 0) {
     1658            double len = Math.sqrt(dx1 * dx1 + dy1 * dy1);
     1659            double dxm = - dy1 * extent / len;
     1660            double dym = dx1 * extent / len;
     1661            if (dx1 * dy2 - dx2 * dy1 < 0) {
     1662                dxm = -dxm;
     1663                dym = -dym;
     1664            }
     1665            return new EastNorth(p2.getX() + dxm, p2.getY() + dym);
     1666        }
     1667        return null;
     1668    }
     1669
    15871670    private boolean isAreaVisible(Path2D.Double area) {
    15881671        Rectangle2D bounds = area.getBounds2D();
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/Multipolygon.java

    r9063 r9077  
    296296        public List<Node> getNodes() {
    297297            return nodes;
     298        }
     299
     300        public List<PolyData> getInners() {
     301            return inners;
    298302        }
    299303
Note: See TracChangeset for help on using the changeset viewer.