View Javadoc
1   /*
2    * Copyright (C) 2016 - 2017 B3Partners B.V.
3    *
4    * This program is free software: you can redistribute it and/or modify
5    * it under the terms of the GNU Affero General Public License as published by
6    * the Free Software Foundation, either version 3 of the License, or
7    * (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU Affero General Public License for more details.
13   *
14   * You should have received a copy of the GNU Affero General Public License
15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16   */
17  package nl.b3p.topnl.converters;
18  
19  import java.io.IOException;
20  import java.io.InvalidClassException;
21  import java.io.StringReader;
22  import javax.xml.parsers.ParserConfigurationException;
23  import javax.xml.transform.TransformerException;
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.geotools.gml3.ArcParameters;
27  import org.geotools.gml3.CircleRadiusTolerance;
28  import org.geotools.xsd.Parser;
29  import org.jdom2.input.DOMBuilder;
30  import org.jdom2.output.XMLOutputter;
31  import org.locationtech.jts.geom.Geometry;
32  import org.locationtech.jts.geom.GeometryFactory;
33  import org.locationtech.jts.geom.PrecisionModel;
34  import org.locationtech.jts.simplify.DouglasPeuckerSimplifier;
35  import org.w3c.dom.Element;
36  import org.xml.sax.SAXException;
37  
38  /**
39   * @author Meine Toonen meinetoonen@b3partners.nl
40   */
41  public class GeometryConverter {
42  
43    protected static final Log log = LogFactory.getLog(GeometryConverter.class);
44  
45    private static final double DISTANCE_TOLERANCE = 0.001;
46    protected static final double LINEARIZATION_TOLERANCE_MULTIPLIER = 0.01; // 0.001;
47  
48    private Parser parser;
49    private GeometryFactory geometryFactory;
50  
51    protected static final int SRID = 28992;
52  
53    public GeometryConverter() {
54      GeometryFactory gf = new GeometryFactory(new PrecisionModel(), SRID);
55  
56      /*  GMLConfiguration gml3Config = new GMLConfiguration(true);
57      gml3Config.setGeometryFactory(gf);
58      gml3Config.setExtendedArcSurfaceSupport(true);*/
59  
60      ArcParameters arcParameters =
61          new ArcParameters(new CircleRadiusTolerance(LINEARIZATION_TOLERANCE_MULTIPLIER)); // new
62      // AbsoluteTolerance(LINEARIZATION_TOLERANCE));
63  
64      org.geotools.gml3.GMLConfiguration gml3Config = new org.geotools.gml3.GMLConfiguration();
65      gml3Config.setExtendedArcSurfaceSupport(true);
66      gml3Config.getContext().registerComponentInstance(gf);
67      gml3Config.getContext().registerComponentInstance(arcParameters);
68      parser = new Parser(gml3Config);
69      this.geometryFactory = gf;
70    }
71  
72    public Geometry convertGeometry(Element el)
73        throws IOException, SAXException, ParserConfigurationException, TransformerException {
74      if (!(el instanceof org.w3c.dom.Element)) {
75        throw new IllegalArgumentException("gml org.w3c.node is not an org.w3c.Element");
76      }
77      // TODO: maybe convert node directly to a source / inputsource / reader / stream for parser.
78      // instead of JDOM detour.
79      org.jdom2.Element elem = new DOMBuilder().build((org.w3c.dom.Element) el);
80      String gmlString = new XMLOutputter().outputString(elem);
81      gmlString = gmlString.replaceAll("gml:", "");
82      // tySstem.out.println("gmlString:" + gmlString);
83      //   parser.getNamespaces().declarePrefix("gml", "http://www.opengis.net/gml/3.2");
84      Object parsedObject = parser.parse(new StringReader(gmlString));
85      if (parsedObject instanceof Geometry) {
86        Geometry geom = (Geometry) parsedObject;
87        if (!geom.isValid()) {
88          geom = geom.buffer(0.0);
89          log.debug("Geometry is invalid. Made valid by buffering with 0");
90        }
91        // arcs can have nodes that are on the same point (28992; 3 digit precision): simplify
92        Geometry simplGeom = DouglasPeuckerSimplifier.simplify(geom, DISTANCE_TOLERANCE);
93        return simplGeom;
94      } else {
95        throw new InvalidClassException(
96            parsedObject.getClass().getCanonicalName(), "Parsed object not of class Geometry.");
97      }
98    }
99  }