001/* *********************************************************************** *
002 * project: org.matsim.*
003 *                                                                         *
004 * *********************************************************************** *
005 *                                                                         *
006 * copyright       : (C) 2008 by the members listed in the COPYING,        *
007 *                   LICENSE and WARRANTY file.                            *
008 * email           : info at matsim dot org                                *
009 *                                                                         *
010 * *********************************************************************** *
011 *                                                                         *
012 *   This program is free software; you can redistribute it and/or modify  *
013 *   it under the terms of the GNU General Public License as published by  *
014 *   the Free Software Foundation; either version 2 of the License, or     *
015 *   (at your option) any later version.                                   *
016 *   See also COPYING, LICENSE and WARRANTY file                           *
017 *                                                                         *
018 * *********************************************************************** */
019
020package org.matsim.vis.kml;
021
022import org.apache.log4j.Logger;
023import org.matsim.api.core.v01.Coord;
024import org.matsim.api.core.v01.Id;
025import org.matsim.api.core.v01.network.Link;
026import org.matsim.api.core.v01.network.Network;
027import org.matsim.api.core.v01.network.Node;
028import org.matsim.api.core.v01.population.Activity;
029import org.matsim.api.core.v01.population.Leg;
030import org.matsim.core.api.internal.MatsimFactory;
031import org.matsim.core.population.routes.NetworkRoute;
032import org.matsim.core.population.routes.RouteUtils;
033import org.matsim.core.utils.geometry.CoordinateTransformation;
034import org.matsim.core.utils.misc.Time;
035
036import net.opengis.kml.v_2_2_0.AbstractFeatureType;
037import net.opengis.kml.v_2_2_0.FolderType;
038import net.opengis.kml.v_2_2_0.LineStringType;
039import net.opengis.kml.v_2_2_0.ObjectFactory;
040import net.opengis.kml.v_2_2_0.PlacemarkType;
041import net.opengis.kml.v_2_2_0.PointType;
042import net.opengis.kml.v_2_2_0.StyleType;
043
044/**
045 * @author dgrether
046 */
047public class NetworkFeatureFactory implements MatsimFactory {
048
049        private static final Logger log = Logger.getLogger(NetworkFeatureFactory.class);
050
051        private CoordinateTransformation coordTransform;
052
053        public static final String ENDP = "</p>";
054        public static final String STARTP = "<p>";
055        public static final String ENDH3 = "</h3>";
056        public static final String STARTH3 = "<h3>";
057        public static final String ENDH2 = "</h2>";
058        public static final String ENDCDATA = "]]>";
059        public static final String STARTH2 = "<h2>";
060        public static final String STARTCDATA = "<![CDATA[";
061
062        private static final String STARTUL = "<ul>";
063        private static final String ENDUL = "</ul>";
064        private static final String STARTLI = "<li>";
065        private static final String ENDLI = "</li>";
066
067        private ObjectFactory kmlObjectFactory = new ObjectFactory();
068        private final Network network;
069
070        public NetworkFeatureFactory(CoordinateTransformation coordTransform, final Network network) {
071                this.coordTransform = coordTransform;
072                this.network = network;
073        }
074
075        public AbstractFeatureType createLinkFeature(final Link l, StyleType networkStyle) {
076                FolderType folder = this.kmlObjectFactory.createFolderType();
077                String description = this.createLinkDescription(l);
078                folder.setName(l.getId().toString());
079
080                PlacemarkType p = this.kmlObjectFactory.createPlacemarkType();
081                p.setName(l.getId().toString());
082
083                Coord fromCoord = this.coordTransform.transform(l.getFromNode().getCoord());
084                Coord toCoord = this.coordTransform.transform(l.getToNode().getCoord());
085                LineStringType line = this.kmlObjectFactory.createLineStringType();
086                line.getCoordinates().add(Double.toString(fromCoord.getX()) + "," + Double.toString(fromCoord.getY()) + ",0.0");
087                line.getCoordinates().add(Double.toString(toCoord.getX()) + "," + Double.toString(toCoord.getY()) + ",0.0");
088                p.setAbstractGeometryGroup(this.kmlObjectFactory.createLineString(line));
089                p.setStyleUrl(networkStyle.getId());
090                p.setDescription(description);
091
092                PlacemarkType pointPlacemark = this.kmlObjectFactory.createPlacemarkType();
093                Coord centerCoord = this.coordTransform.transform(l.getCoord());
094                PointType point = this.kmlObjectFactory.createPointType();
095                point.getCoordinates().add(Double.toString(centerCoord.getX()) + "," + Double.toString(centerCoord.getY()) + ",0.0");
096                pointPlacemark.setAbstractGeometryGroup(this.kmlObjectFactory.createPoint(point));
097                pointPlacemark.setStyleUrl(networkStyle.getId());
098                pointPlacemark.setDescription(description);
099
100                folder.getAbstractFeatureGroup().add(this.kmlObjectFactory.createPlacemark(pointPlacemark));
101                folder.getAbstractFeatureGroup().add(this.kmlObjectFactory.createPlacemark(p));
102
103                return folder;
104        }
105
106        public AbstractFeatureType createNodeFeature(final Node n, StyleType networkStyle) {
107                PlacemarkType p = this.kmlObjectFactory.createPlacemarkType();
108                p.setName(n.getId().toString());
109
110                Coord coord = this.coordTransform.transform(n.getCoord());
111                PointType point = this.kmlObjectFactory.createPointType();
112                point.getCoordinates().add(Double.toString(coord.getX()) + "," + Double.toString(coord.getY()) + ",0.0");
113                p.setAbstractGeometryGroup(this.kmlObjectFactory.createPoint(point));
114
115                p.setStyleUrl(networkStyle.getId());
116                p.setDescription(this.createNodeDescription(n));
117
118                return p;
119        }
120
121        public AbstractFeatureType createActFeature(Activity act, StyleType style) {
122
123                PlacemarkType p = this.kmlObjectFactory.createPlacemarkType();
124                p.setName("Activity on link: " + act.getLinkId().toString());
125
126                Coord coord = this.coordTransform.transform(act.getCoord());
127                PointType point = this.kmlObjectFactory.createPointType();
128                point.getCoordinates().add(Double.toString(coord.getX()) + "," + Double.toString(coord.getY()) + ",0.0");
129                p.setAbstractGeometryGroup(this.kmlObjectFactory.createPoint(point));
130
131                p.setStyleUrl(style.getId());
132                return p;
133        }
134
135        public AbstractFeatureType createLegFeature(Leg leg, StyleType style) {
136                FolderType folder = this.kmlObjectFactory.createFolderType();
137                folder.setName(leg.getMode() + "_" + Time.writeTime(leg.getDepartureTime().seconds()));
138
139                for (Id<Link> linkId : ((NetworkRoute) leg.getRoute()).getLinkIds()) {
140                        Link l = this.network.getLinks().get(linkId);
141
142                        AbstractFeatureType abstractFeature = this.createLinkFeature(l, style);
143                        if (abstractFeature.getClass().equals(FolderType.class)) {
144                                folder.getAbstractFeatureGroup().add(this.kmlObjectFactory.createFolder((FolderType) abstractFeature));
145                        } else {
146                                log.warn("Not yet implemented: Adding link KML features of type" + abstractFeature.getClass());
147                        }
148                }
149                for (Node n : RouteUtils.getNodes((NetworkRoute) leg.getRoute(), this.network)) {
150
151                        AbstractFeatureType abstractFeature = this.createNodeFeature(n, style);
152                        if (abstractFeature.getClass().equals(PlacemarkType.class)) {
153                                folder.getAbstractFeatureGroup().add(this.kmlObjectFactory.createPlacemark((PlacemarkType) abstractFeature));
154                        } else {
155                                log.warn("Not yet implemented: Adding node KML features of type" + abstractFeature.getClass());
156                        }
157                }
158
159                return folder;
160        }
161
162        private String createLinkDescription(Link l) {
163                StringBuilder buffer = new StringBuilder(100);
164//              buffer.append(NetworkFeatureFactory.STARTCDATA);
165                buffer.append(NetworkFeatureFactory.STARTH2);
166                buffer.append("Link: " );
167                buffer.append(l.getId());
168                buffer.append(NetworkFeatureFactory.ENDH2);
169                buffer.append(NetworkFeatureFactory.STARTH3);
170                buffer.append("From Node: ");
171                buffer.append(l.getFromNode().getId());
172                buffer.append(NetworkFeatureFactory.ENDH3);
173                buffer.append(NetworkFeatureFactory.STARTP);
174                buffer.append(NetworkFeatureFactory.ENDP);
175                buffer.append(NetworkFeatureFactory.STARTH3);
176                buffer.append("To Node: ");
177                buffer.append(l.getToNode().getId());
178                buffer.append(NetworkFeatureFactory.ENDH3);
179                buffer.append(NetworkFeatureFactory.STARTP);
180                buffer.append(NetworkFeatureFactory.ENDP);
181
182                buffer.append(NetworkFeatureFactory.STARTH3);
183                buffer.append("Attributes: ");
184                buffer.append(NetworkFeatureFactory.ENDH3);
185                buffer.append(NetworkFeatureFactory.STARTP);
186                buffer.append(STARTUL);
187                buffer.append(STARTLI);
188                buffer.append("Freespeed: ");
189                buffer.append(l.getFreespeed());
190                buffer.append(ENDLI);
191                buffer.append(STARTLI);
192                buffer.append("Capacity: ");
193                buffer.append(l.getCapacity());
194                buffer.append(ENDLI);
195                buffer.append(STARTLI);
196                buffer.append("Number of Lanes: ");
197                buffer.append(l.getNumberOfLanes());
198                buffer.append(ENDLI);
199                buffer.append(STARTLI);
200                buffer.append("Length: ");
201                buffer.append(l.getLength());
202                buffer.append(ENDLI);
203                buffer.append(ENDUL);
204                buffer.append(NetworkFeatureFactory.ENDP);
205
206//              buffer.append(NetworkFeatureFactory.ENDCDATA);
207
208                return buffer.toString();
209        }
210
211        private String createNodeDescription(Node n) {
212                StringBuilder buffer = new StringBuilder(100);
213//              buffer.append(NetworkFeatureFactory.STARTCDATA);
214                buffer.append(NetworkFeatureFactory.STARTH2);
215                buffer.append("Node: " );
216                buffer.append(n.getId());
217                buffer.append(NetworkFeatureFactory.ENDH2);
218                buffer.append(NetworkFeatureFactory.STARTH3);
219                buffer.append("Inlinks");
220                buffer.append(NetworkFeatureFactory.ENDH3);
221                buffer.append(NetworkFeatureFactory.STARTP);
222                buffer.append(STARTUL);
223                for (Link l : n.getInLinks().values()) {
224                        buffer.append(STARTLI);
225                        buffer.append("Link: " );
226                        buffer.append(l.getId());
227                        buffer.append(" from Node: " );
228                        buffer.append(l.getFromNode().getId());
229                        buffer.append(ENDLI);
230                }
231                buffer.append(ENDUL);
232                buffer.append(NetworkFeatureFactory.ENDP);
233                buffer.append(NetworkFeatureFactory.STARTH3);
234                buffer.append("Outlinks");
235                buffer.append(NetworkFeatureFactory.ENDH3);
236                buffer.append(NetworkFeatureFactory.STARTP);
237                buffer.append(STARTUL);
238                for (Link l : n.getOutLinks().values()) {
239                        buffer.append(STARTLI);
240                        buffer.append("Link: " );
241                        buffer.append(l.getId());
242                        buffer.append(" to Node: ");
243                        buffer.append(l.getToNode().getId());
244                        buffer.append(ENDLI);
245                }
246                buffer.append(ENDUL);
247                buffer.append(NetworkFeatureFactory.ENDP);
248//              buffer.append(NetworkFeatureFactory.ENDCDATA);
249                return buffer.toString();
250        }
251
252}