Changeset 1190 in josm


Ignore:
Timestamp:
2008-12-29T19:21:40+01:00 (16 years ago)
Author:
stoecker
Message:

added first part of multipolygon drawing

Location:
trunk/src/org/openstreetmap/josm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/Way.java

    r1180 r1190  
    117117        return name;
    118118    }
     119
     120    public Boolean isClosed() {
     121        int s = nodes.size();
     122        return s >= 3 && nodes.get(0) == nodes.get(s-1);
     123    }
    119124}
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java

    r1169 r1190  
    1212import java.awt.Stroke;
    1313import java.awt.geom.GeneralPath;
     14import java.util.ArrayList;
    1415import java.util.Collection;
    1516import java.util.LinkedList;
     
    2324import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2425import org.openstreetmap.josm.data.osm.Relation;
     26import org.openstreetmap.josm.data.osm.RelationMember;
    2527import org.openstreetmap.josm.data.osm.Way;
    2628import org.openstreetmap.josm.data.osm.visitor.SimplePaintVisitor;
     
    4648    protected double circum;
    4749    protected String regionalNameOrder[];
     50    protected Collection<Way> alreadyDrawnWays = new LinkedList<Way>();
     51    protected Collection<Way> alreadyDrawnAreas = new LinkedList<Way>();
    4852
    4953    protected boolean isZoomOk(ElemStyle e) {
     
    8791        if(w.nodes.size() < 2)
    8892            return;
    89         // show direction arrows, if draw.segment.relevant_directions_only is not set, the way is tagged with a direction key
    90         // (even if the tag is negated as in oneway=false) or the way is selected
    91         boolean showDirection = w.selected || ((!useRealWidth) && (showDirectionArrow
    92          && (!showRelevantDirectionsOnly || w.hasDirectionKeys)));
    93 
    94         Color color = untaggedColor;
    95         int width = defaultSegmentWidth;
    96         int realWidth = 0; //the real width of the element in meters
    97         boolean dashed = false;
     93
    9894        ElemStyle wayStyle = styles.get(w);
    9995
     
    10298
    10399        LineElemStyle l = null;
     100        Color areacolor = untaggedColor;
    104101        if(wayStyle!=null)
    105102        {
    106             Color areacolor = untaggedColor;
    107103            boolean area = false;
    108104            if(wayStyle instanceof LineElemStyle)
     
    111107            {
    112108                areacolor = ((AreaElemStyle)wayStyle).color;
    113                 color = areacolor;
    114109                l = ((AreaElemStyle)wayStyle).line;
    115110                area = true;
    116111            }
    117             if(l != null)
    118             {
    119                 color = l.color;
    120                 width = l.width;
    121                 realWidth = l.realWidth;
    122                 dashed = l.dashed;
    123             }
    124112            if (area && fillAreas)
    125113                drawWayAsArea(w, areacolor);
    126114        }
    127115
     116        drawWay(w, l, areacolor);
     117    }
     118
     119    public void drawWay(Way w, LineElemStyle l, Color color) {
     120        // show direction arrows, if draw.segment.relevant_directions_only is not set,
     121        // the way is tagged with a direction key
     122        // (even if the tag is negated as in oneway=false) or the way is selected
     123        boolean showDirection = w.selected || ((!useRealWidth) && (showDirectionArrow
     124        && (!showRelevantDirectionsOnly || w.hasDirectionKeys)));
     125        int width = defaultSegmentWidth;
     126        int realWidth = 0; //the real width of the element in meters
     127        boolean dashed = false;
     128
     129        if(l != null)
     130        {
     131            color = l.color;
     132            width = l.width;
     133            realWidth = l.realWidth;
     134            dashed = l.dashed;
     135        }
    128136        if (realWidth > 0 && useRealWidth && !showDirection)
    129137        {
     
    200208    }
    201209
    202     public void visit(Relation e) {
    203         // relations are not (yet?) drawn.
    204     }
    205 
    206     // This assumes that all segments are aligned in the same direction!
     210    public Collection<Way> joinWays(Collection<Way> join)
     211    {
     212        Collection<Way> res = new LinkedList<Way>();
     213        Object[] joinArray = join.toArray();
     214        int left = join.size();
     215        while(left != 0)
     216        {
     217            Way w = null;
     218            Boolean selected = false;
     219            ArrayList<Node> n = null;
     220            Boolean joined = true;
     221            while(joined && left != 0)
     222            {
     223                joined = false;
     224                for(int i = 0; i < joinArray.length && left != 0; ++i)
     225                {
     226                    if(joinArray[i] != null)
     227                    {
     228                        Way c = (Way)joinArray[i];
     229                        if(w == null)
     230                        { w = c; selected = w.selected; joinArray[i] = null; --left; }
     231                        else
     232                        {
     233                            int mode = 0;
     234                            int cl = c.nodes.size()-1;
     235                            int nl;
     236                            if(n == null)
     237                            {
     238                                nl = w.nodes.size()-1;
     239                                if(w.nodes.get(nl) == c.nodes.get(0)) mode = 21;
     240                                else if(w.nodes.get(nl) == c.nodes.get(cl)) mode = 22;
     241                                else if(w.nodes.get(0) == c.nodes.get(0)) mode = 11;
     242                                else if(w.nodes.get(0) == c.nodes.get(cl)) mode = 12;
     243                            }
     244                            else
     245                            {
     246                                nl = n.size()-1;
     247                                if(n.get(nl) == c.nodes.get(0)) mode = 21;
     248                                else if(n.get(0) == c.nodes.get(cl)) mode = 12;
     249                                else if(n.get(0) == c.nodes.get(0)) mode = 11;
     250                                else if(n.get(nl) == c.nodes.get(cl)) mode = 22;
     251                            }
     252                            if(mode != 0)
     253                            {
     254                                joinArray[i] = null;
     255                                joined = true;
     256                                if(c.selected) selected = true;
     257                                --left;
     258                                if(n == null) n = new ArrayList(w.nodes);
     259System.out.println("old: " + n);
     260System.out.println("new: " + c.nodes);
     261                                n.remove((mode == 21 || mode == 22) ? nl : 0);
     262                                if(mode == 21)
     263                                    n.addAll(c.nodes);
     264                                else if(mode == 12)
     265                                    n.addAll(0, c.nodes);
     266                                else if(mode == 22)
     267                                {
     268                                    for(Node node : c.nodes)
     269                                        n.add(nl, node);
     270System.out.println("ERROR: Joining way reversed: " + c);
     271                                }
     272                                else /* mode == 11 */
     273                                {
     274                                    for(Node node : c.nodes)
     275                                        n.add(0, node);
     276System.out.println("ERROR: Joining way reversed: " + c);
     277                                }
     278System.out.println("joined: " + n);
     279                            }
     280                        }
     281                    }
     282                } /* for(i = ... */
     283            } /* while(joined) */
     284            if(n != null)
     285            {
     286                w = new Way(w);
     287                w.nodes.clear();
     288                w.nodes.addAll(n);
     289                w.selected = selected;
     290            }
     291            if(!w.isClosed())
     292            {
     293System.out.println("ERROR: multipolygon way is not closed." + w);
     294            }
     295            res.add(w);
     296        } /* while(left != 0) */
     297
     298        return res;
     299    }
     300
     301    public void visit(Relation r) {
     302        // draw multipolygon relations including their ways
     303        // other relations are not (yet?) drawn.
     304        if (r.incomplete) return;
     305
     306        if(!Main.pref.getBoolean("mappaint.multipolygon",false)) return;
     307
     308        if(!"multipolygon".equals(r.keys.get("type"))) return;
     309
     310        Collection<Way> inner = new LinkedList<Way>();
     311        Collection<Way> outer = new LinkedList<Way>();
     312        Collection<Way> innerclosed = new LinkedList<Way>();
     313        Collection<Way> outerclosed = new LinkedList<Way>();
     314
     315        for (RelationMember m : r.members)
     316        {
     317            if (!m.member.incomplete && !m.member.deleted)
     318            {
     319                if(m.member instanceof Way)
     320                {
     321                    Way w = (Way) m.member;
     322                    if(w.nodes.size() < 2)
     323                    {
     324System.out.println("ERROR: Way with less than two points " + w);
     325                    }
     326                    else if("inner".equals(m.role))
     327                        inner.add(w);
     328                    else if("outer".equals(m.role))
     329                        outer.add(w);
     330                    else
     331                    {
     332System.out.println("ERROR: No useful role for Way " + w);
     333                        if(m.role == null || m.role.length() == 0)
     334                            outer.add(w);
     335                    }
     336                }
     337                else
     338                {
     339System.out.println("ERROR: Non-Way in multipolygon " + m.member);
     340                }
     341            }
     342        }
     343
     344        ElemStyle wayStyle = styles.get(r);
     345        /* find one wayStyle, prefer the style from Relation or take the first
     346        one of outer rings */
     347        if(wayStyle == null || !(wayStyle instanceof AreaElemStyle))
     348        {
     349            for (Way w : outer)
     350            {
     351               if(wayStyle == null || !(wayStyle instanceof AreaElemStyle))
     352                   wayStyle = styles.get(w);
     353            }
     354        }
     355
     356        if(wayStyle != null && wayStyle instanceof AreaElemStyle)
     357        {
     358            Boolean zoomok = isZoomOk(wayStyle);
     359            Collection<Way> join = new LinkedList<Way>();
     360
     361            /* parse all outer rings and join them */
     362            for (Way w : outer)
     363            {
     364                if(w.isClosed()) outerclosed.add(w);
     365                else join.add(w);
     366            }
     367            if(join.size() != 0)
     368            {
     369                for(Way w : joinWays(join))
     370                    outerclosed.add(w);
     371            }
     372
     373            /* parse all inner rings and join them */
     374            join.clear();
     375            for (Way w : inner)
     376            {
     377                if(w.isClosed()) innerclosed.add(w);
     378                else join.add(w);
     379            }
     380            if(join.size() != 0)
     381            {
     382                for(Way w : joinWays(join))
     383                    innerclosed.add(w);
     384            }
     385
     386            /* handle inside out stuff */
     387
     388            if(zoomok) /* draw */
     389            {
     390                for (Way w : outerclosed)
     391                {
     392                    Color color = w.selected ? selectedColor
     393                    : ((AreaElemStyle)wayStyle).color;
     394                    Polygon polygon = new Polygon();
     395                    Point pOuter = null;
     396
     397                    for (Node n : w.nodes)
     398                    {
     399                        pOuter = nc.getPoint(n.eastNorth);
     400                        polygon.addPoint(pOuter.x,pOuter.y);
     401                    }
     402                    for (Way wInner : innerclosed)
     403                    {
     404                        for (Node n : wInner.nodes)
     405                        {
     406                            Point pInner = nc.getPoint(n.eastNorth);
     407                            polygon.addPoint(pInner.x,pInner.y);
     408                        }
     409                        polygon.addPoint(pOuter.x,pOuter.y);
     410                    }
     411
     412                    g.setColor(new Color( color.getRed(), color.getGreen(),
     413                    color.getBlue(), fillAlpha));
     414
     415                    g.fillPolygon(polygon);
     416                    alreadyDrawnAreas.add(w);
     417                }
     418            }
     419            for (Way wInner : inner)
     420            {
     421                ElemStyle innerStyle = styles.get(wInner);
     422                if(innerStyle == null)
     423                {
     424                    if(zoomok)
     425                        drawWay(wInner, ((AreaElemStyle)wayStyle).line,
     426                        ((AreaElemStyle)wayStyle).color);
     427                    alreadyDrawnWays.add(wInner);
     428                }
     429                else if(wayStyle.equals(innerStyle))
     430                {
     431System.out.println("WARNING: Inner waystyle equals multipolygon for way " + wInner);
     432                    alreadyDrawnAreas.add(wInner);
     433                }
     434            }
     435            for (Way wOuter : outer)
     436            {
     437                ElemStyle outerStyle = styles.get(wOuter);
     438                if(outerStyle == null)
     439                {
     440                    if(zoomok)
     441                        drawWay(wOuter, ((AreaElemStyle)wayStyle).line,
     442                        ((AreaElemStyle)wayStyle).color);
     443                    alreadyDrawnWays.add(wOuter);
     444                }
     445                else
     446                {
     447                    if(!wayStyle.equals(outerStyle))
     448System.out.println("ERROR: Outer waystyle does not match multipolygon for way " + wOuter);
     449                    alreadyDrawnAreas.add(wOuter);
     450                }
     451            }
     452        }
     453    }
     454
    207455    protected void drawWayAsArea(Way w, Color color)
    208456    {
     
    338586        regionalNameOrder = Main.pref.get("mappaint.nameOrder", "name:"+currentLocale+";name;int_name").split(";");
    339587
    340         if (styles.hasAreas()) {
     588        if (fillAreas && styles.hasAreas()) {
    341589            Collection<Way> noAreaWays = new LinkedList<Way>();
    342590
    343             for (final OsmPrimitive osm : data.ways)
    344                 if (!osm.incomplete && !osm.deleted && styles.isArea((Way)osm))
     591            for (final Relation osm : data.relations)
     592            {
     593                if (!osm.deleted && !osm.selected)
     594                {
    345595                    osm.visit(this);
    346                 else if (!osm.deleted && !osm.incomplete)
    347                     noAreaWays.add((Way)osm);
    348 
     596                }
     597            }
     598
     599            for (final Way osm : data.ways)
     600            {
     601                if (!osm.incomplete && !osm.deleted && !alreadyDrawnWays.contains(osm))
     602                {
     603                    if(styles.isArea((Way)osm) && !alreadyDrawnAreas.contains(osm))
     604                        osm.visit(this);
     605                    else
     606                        noAreaWays.add((Way)osm);
     607                }
     608            }
     609            // free that stuff
     610            alreadyDrawnWays = null;
     611            alreadyDrawnAreas = null;
     612
     613            fillAreas = false;
    349614            for (final OsmPrimitive osm : noAreaWays)
    350615                osm.visit(this);
  • trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java

    r1169 r1190  
    88
    99    public int priority;
     10    public String code;
     11
     12    public Boolean equals(ElemStyle s)
     13    {
     14        return s != null && s.code.equals(code);
     15    }
    1016}
    1117
  • trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java

    r1169 r1190  
    55import java.util.LinkedList;
    66import java.util.List;
     7import java.util.Map;
    78import java.util.Iterator;
    89
    910import org.openstreetmap.josm.data.osm.Node;
     11import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1012import org.openstreetmap.josm.data.osm.OsmUtils;
     13import org.openstreetmap.josm.data.osm.Relation;
    1114import org.openstreetmap.josm.data.osm.Way;
    1215import org.openstreetmap.josm.Main;
     
    4649    public void add(String name, String k, String v, String b, LineElemStyle style)
    4750    {
    48         getStyleSet(name, true).lines.put(getKey(k,v,b), style);
     51        String key = getKey(k,v,b);
     52        style.code = key;
     53        getStyleSet(name, true).lines.put(key, style);
    4954    }
    5055
    5156    public void addModifier(String name, String k, String v, String b, LineElemStyle style)
    5257    {
    53         getStyleSet(name, true).modifiers.put(getKey(k,v,b), style);
     58        String key = getKey(k,v,b);
     59        style.code = key;
     60        getStyleSet(name, true).modifiers.put(key, style);
    5461    }
    5562
    5663    public void add(String name, String k, String v, String b, AreaElemStyle style)
    5764    {
    58         getStyleSet(name, true).areas.put(getKey(k,v,b), style);
     65        String key = getKey(k,v,b);
     66        style.code = key;
     67        getStyleSet(name, true).areas.put(key, style);
    5968    }
    6069
    6170    public void add(String name, String k, String v, String b, IconElemStyle style)
    6271    {
    63         getStyleSet(name, true).icons.put(getKey(k,v,b), style);
     72        String key = getKey(k,v,b);
     73        style.code = key;
     74        getStyleSet(name, true).icons.put(key, style);
    6475    }
    6576
     
    109120    }
    110121
    111     public ElemStyle get(Way w)
    112     {
    113         StyleSet ss = getStyleSet(null, false);
    114         if(ss == null || w.keys == null)
    115             return null;
     122    private ElemStyle get(Map<String, String> keys, StyleSet ss)
     123    {
    116124        AreaElemStyle retArea = null;
    117125        LineElemStyle retLine = null;
    118126        String linestring = null;
    119127        HashMap<String, LineElemStyle> over = new HashMap<String, LineElemStyle>();
    120         Iterator<String> iterator = w.keys.keySet().iterator();
     128        Iterator<String> iterator = keys.keySet().iterator();
    121129        while(iterator.hasNext())
    122130        {
    123131            String key = iterator.next();
    124             String val = w.keys.get(key);
     132            String val = keys.get(key);
    125133            AreaElemStyle styleArea;
    126134            LineElemStyle styleLine;
     
    173181    }
    174182
    175     public boolean isArea(Way w)
    176     {
    177         StyleSet ss = getStyleSet(null, false);
    178         if(ss != null && w.keys != null)
    179         {
    180             Iterator<String> iterator = w.keys.keySet().iterator();
    181             while(iterator.hasNext())
    182             {
    183                 String key = iterator.next();
    184                 String val = w.keys.get(key);
    185                 if(ss.areas.containsKey("n" + key + "=" + val)
    186                 || ss.areas.containsKey("n" + key + "=" + OsmUtils.getNamedOsmBoolean(val))
    187                 || ss.areas.containsKey("x" + key))
    188                     return true;
    189             }
     183    public ElemStyle get(Way w)
     184    {
     185        StyleSet ss = getStyleSet(null, false);
     186        return (ss == null || w.keys == null) ? null : get(w.keys, ss);
     187    }
     188
     189    public ElemStyle get(Relation r)
     190    {
     191        StyleSet ss = getStyleSet(null, false);
     192        return (ss == null || r.keys == null) ? null : get(r.keys, ss);
     193    }
     194
     195    private boolean isArea(Map<String, String> keys, StyleSet ss)
     196    {
     197        Iterator<String> iterator = keys.keySet().iterator();
     198        while(iterator.hasNext())
     199        {
     200            String key = iterator.next();
     201            String val = keys.get(key);
     202            if(ss.areas.containsKey("n" + key + "=" + val)
     203            || ss.areas.containsKey("n" + key + "=" + OsmUtils.getNamedOsmBoolean(val))
     204            || ss.areas.containsKey("x" + key))
     205                return true;
    190206        }
    191207        return false;
    192208    }
     209
     210    public boolean isArea(OsmPrimitive o)
     211    {
     212        StyleSet ss = getStyleSet(null, false);
     213        return (ss != null && o.keys != null && !(o instanceof Node))
     214        ? isArea(o.keys, ss) : false;
     215    }
     216
    193217    public boolean hasAreas()
    194218    {
Note: See TracChangeset for help on using the changeset viewer.