Statistics
| Revision:

root / trunk / libraries / libTopology / src / com / vividsolutions / jcs / plugin / conflate / roads / dra / FindJoggedJunctionsPlugIn.java @ 22873

History | View | Annotate | Download (6.24 KB)

1
package com.vividsolutions.jcs.plugin.conflate.roads.dra;
2
import java.awt.Color;
3
import com.vividsolutions.jcs.conflate.roads.model.RoadNode;
4
import com.vividsolutions.jcs.graph.DirectedEdge;
5
import com.vividsolutions.jts.geom.Coordinate;
6
import com.vividsolutions.jts.util.Assert;
7
import com.vividsolutions.jump.feature.*;
8
import com.vividsolutions.jump.geom.Angle;
9
import com.vividsolutions.jump.util.StringUtil;
10
import com.vividsolutions.jump.workbench.WorkbenchContext;
11
import com.vividsolutions.jump.workbench.model.Layer;
12
import com.vividsolutions.jump.workbench.model.LayerManager;
13
import com.vividsolutions.jump.workbench.ui.MultiInputDialog;
14
public class FindJoggedJunctionsPlugIn extends
15
                AbstractFindTopologyFromNodesPlugIn {
16
        protected void addMatchingTopologyFeatures(RoadNode node,
17
                        FeatureCollection featureCollection) {
18
                Feature joggedJunctionFeature = joggedJunctionFeature(node);
19
                if (joggedJunctionFeature != null) {
20
                        featureCollection.add(joggedJunctionFeature);
21
                }
22
        }
23
        private Coordinate coordinate(int i, DirectedEdge d) {
24
                return d.getEdgeDirection() ? line(d).getCoordinateN(i) : line(d)
25
                                .getCoordinateN(line(d).getNumPoints() - 1 - i);
26
        }
27
        private Feature createJoggedJunctionFeature(DirectedEdge jogEdge0,
28
                        DirectedEdge nextEdge0, DirectedEdge jogEdge1,
29
                        DirectedEdge nextEdge1) {
30
                Feature feature = new BasicFeature(schema);
31
                feature.setAttribute("GEOMETRY", getFactory().createPoint(
32
                                jogEdge0.getFromNode().getCoordinate()));
33
                feature.setAttribute("OFFSET", new Double(offset(jogEdge0, nextEdge0,
34
                                jogEdge1, nextEdge1)));
35
                feature.setAttribute("KINK ANGLE",
36
                                new Double(Angle.toDegrees(kinkAngle(jogEdge0, nextEdge0,
37
                                                jogEdge1, nextEdge1))));
38
                feature.setAttribute("SOURCE", network(jogEdge0).getName());
39
                return feature;
40
        }
41
        protected Layer createLayer(FeatureCollection featureCollection,
42
                        LayerManager layerManager) {
43
                return new Layer("Jogged Junctions", Color.black, featureCollection,
44
                                layerManager);
45
        }
46
        private double firstSegmentAngle(DirectedEdge d) {
47
                return Angle.angle(coordinate(0, d), coordinate(1, d));
48
        }
49
        protected FeatureSchema getSchema() {
50
                return schema;
51
        }
52
        private double kinkAngle(DirectedEdge jogEdge0, DirectedEdge nextEdge0,
53
                        DirectedEdge jogEdge1, DirectedEdge nextEdge1) {
54
                return Math.PI
55
                                - Math.min(Angle.diff(firstSegmentAngle(jogEdge0),
56
                                                secondSegmentAngle(jogEdge0)), Angle.diff(
57
                                                firstSegmentAngle(jogEdge1),
58
                                                secondSegmentAngle(jogEdge1)));
59
        }
60
        private Feature joggedJunctionFeature(DirectedEdge jogEdge0,
61
                        DirectedEdge nextEdge0, DirectedEdge jogEdge1,
62
                        DirectedEdge nextEdge1) {
63
                if (line(jogEdge0).getNumPoints() < 3) {
64
                        return null;
65
                }
66
                if (line(jogEdge1).getNumPoints() < 3) {
67
                        return null;
68
                }
69
                if (kinkAngle(jogEdge0, nextEdge0, jogEdge1, nextEdge1) > maxKinkAngle) {
70
                        return null;
71
                }
72
                if (offset(jogEdge0, nextEdge0, jogEdge1, nextEdge1) > maxOffset) {
73
                        return null;
74
                }
75
                if (Angle.getTurn(firstSegmentAngle(nextEdge0),
76
                                firstSegmentAngle(jogEdge0)) != Angle.getTurn(
77
                                firstSegmentAngle(jogEdge0), secondSegmentAngle(jogEdge0))) {
78
                        return null;
79
                }
80
                if (Angle.getTurn(firstSegmentAngle(nextEdge1),
81
                                firstSegmentAngle(jogEdge1)) != Angle.getTurn(
82
                                firstSegmentAngle(jogEdge1), secondSegmentAngle(jogEdge1))) {
83
                        return null;
84
                }
85
                return createJoggedJunctionFeature(jogEdge0, nextEdge0, jogEdge1,
86
                                nextEdge1);
87
        }
88
        private Feature joggedJunctionFeature(RoadNode node) {
89
                if (node.getDegree() != 4) {
90
                        return null;
91
                }
92
                DirectedEdge[] directedEdges = (DirectedEdge[]) node.getOutEdges()
93
                                .getEdges().toArray(new DirectedEdge[4]);
94
                Feature joggedJunctionFeature = joggedJunctionFeature(directedEdges[0],
95
                                directedEdges[1], directedEdges[2], directedEdges[3]);
96
                if (joggedJunctionFeature != null) {
97
                        return joggedJunctionFeature;
98
                }
99
                joggedJunctionFeature = joggedJunctionFeature(directedEdges[1],
100
                                directedEdges[0], directedEdges[3], directedEdges[2]);
101
                if (joggedJunctionFeature != null) {
102
                        return joggedJunctionFeature;
103
                }
104
                joggedJunctionFeature = joggedJunctionFeature(directedEdges[1],
105
                                directedEdges[2], directedEdges[3], directedEdges[0]);
106
                if (joggedJunctionFeature != null) {
107
                        return joggedJunctionFeature;
108
                }
109
                joggedJunctionFeature = joggedJunctionFeature(directedEdges[2],
110
                                directedEdges[1], directedEdges[0], directedEdges[3]);
111
                if (joggedJunctionFeature != null) {
112
                        return joggedJunctionFeature;
113
                }
114
                return null;
115
        }
116
        protected String noTopologiesFoundMessage() {
117
                return "No jogged junctions found";
118
        }
119
        private double offset(DirectedEdge jogEdge, DirectedEdge nextEdge) {
120
                return firstSegmentLength(jogEdge)
121
                                * Math.sin(Angle.diff(firstSegmentAngle(jogEdge),
122
                                                secondSegmentAngle(jogEdge)))
123
                                / Math.sin(supplement(Angle.diff(firstSegmentAngle(nextEdge),
124
                                                secondSegmentAngle(jogEdge))));
125
        }
126
        private double offset(DirectedEdge jogEdge0, DirectedEdge nextEdge0,
127
                        DirectedEdge jogEdge1, DirectedEdge nextEdge1) {
128
                return offset(jogEdge0, nextEdge0) + offset(jogEdge1, nextEdge1);
129
        }
130
        protected boolean prompt(WorkbenchContext context) {
131
                final MultiInputDialog dialog = new MultiInputDialog(context
132
                                .getWorkbench().getFrame(), getName(), true);
133
                final String maxOffsetDescription = "Max Offset";
134
                final String maxKinkAngleDescription = "Max Kink Angle (degrees)";
135
                addNumericField(20, maxOffsetDescription, dialog, context);
136
                addAcuteAngleField(175, 180, maxKinkAngleDescription, dialog, context);
137
                dialog.setVisible(true);
138
                if (!dialog.wasOKPressed()) {
139
                        return false;
140
                }
141
                maxOffset = value(maxOffsetDescription, dialog, context);
142
                maxKinkAngle = Angle.toRadians(value(maxKinkAngleDescription, dialog,
143
                                context));
144
                return true;
145
        }
146
        private double secondSegmentAngle(DirectedEdge d) {
147
                return Angle.angle(coordinate(1, d), coordinate(2, d));
148
        }
149
        private double supplement(double angle) {
150
                Assert.isTrue(Math.PI >= angle);
151
                return Math.PI - angle;
152
        }
153
        protected String topologiesFoundMessage(int topologies) {
154
                return topologies + " jogged junction" + StringUtil.s(topologies)
155
                                + " found";
156
        }
157
        private double maxKinkAngle;
158
        private double maxOffset;
159
        private FeatureSchema schema = new FeatureSchema() {
160
                {
161
                        addAttribute("GEOMETRY", AttributeType.GEOMETRY);
162
                        addAttribute("OFFSET", AttributeType.DOUBLE);
163
                        addAttribute("KINK ANGLE", AttributeType.DOUBLE);
164
                        addAttribute("SOURCE", AttributeType.STRING);
165
                }
166
        };
167
}