View Javadoc
1   package fr.ifremer.dali.dao.technical;
2   
3   /*
4    * #%L
5    * Dali :: Core
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2014 - 2015 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  import com.vividsolutions.jts.geom.Coordinate;
27  import com.vividsolutions.jts.geom.Envelope;
28  import com.vividsolutions.jts.geom.Geometry;
29  import fr.ifremer.dali.dto.CoordinateDTO;
30  import fr.ifremer.dali.dto.DaliBeanFactory;
31  import fr.ifremer.quadrige3.core.dao.technical.Assert;
32  import org.apache.commons.lang3.StringUtils;
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
35  import org.geotools.geometry.jts.JTS;
36  import org.geotools.referencing.crs.DefaultGeographicCRS;
37  import org.opengis.referencing.operation.TransformException;
38  
39  import java.util.Objects;
40  
41  /**
42   * Geometry utility class
43   * <p/>
44   * Created by Ludovic on 16/04/2015.
45   */
46  public class Geometries extends fr.ifremer.quadrige3.core.dao.technical.Geometries {
47  
48      private static final Log LOG = LogFactory.getLog(Geometries.class);
49  
50      /**
51       * <p>getCoordinate.</p>
52       *
53       * @param position a {@link java.lang.String} object.
54       * @return a {@link fr.ifremer.dali.dto.CoordinateDTO} object.
55       */
56      public static CoordinateDTO getCoordinate(String position) {
57  
58          CoordinateDTO coordinate = DaliBeanFactory.newCoordinateDTO();
59  
60          if (StringUtils.isNotBlank(position)) {
61  
62              // Keep WTK (raw data)
63              coordinate.setWkt(position);
64  
65              // Convert to Geometry
66              Geometry geometry = getGeometry(position);
67  
68              switch (geometry.getNumPoints()) {
69                  case 1:
70                      coordinate.setMinLongitude(geometry.getCoordinate().x);
71                      coordinate.setMinLatitude(geometry.getCoordinate().y);
72                      break;
73                  case 2:
74                      coordinate.setMinLongitude(geometry.getCoordinates()[0].x);
75                      coordinate.setMinLatitude(geometry.getCoordinates()[0].y);
76                      coordinate.setMaxLongitude(geometry.getCoordinates()[1].x);
77                      coordinate.setMaxLatitude(geometry.getCoordinates()[1].y);
78                      break;
79                  default:
80                      Envelope envelope = geometry.getEnvelopeInternal();
81                      coordinate.setMinLongitude(envelope.getMinX());
82                      coordinate.setMinLatitude(envelope.getMinY());
83                      if (envelope.getWidth() > 0 || envelope.getHeight() > 0) {
84                          coordinate.setMaxLongitude(envelope.getMaxX());
85                          coordinate.setMaxLatitude(envelope.getMaxY());
86                      }
87                      break;
88              }
89          }
90  
91          return coordinate;
92      }
93  
94      public static Geometry getGeometry(CoordinateDTO coordinate) {
95          Assert.isTrue(isValid(coordinate), "the CoordinateDTO object is invalid : " + toString(coordinate));
96          return getGeometry(getPosition(coordinate));
97      }
98  
99      public static String getPosition(CoordinateDTO coordinate) {
100         if (!isValid(coordinate)) return null;
101 
102         if (isPoint(coordinate)) {
103             Geometry geometry = createPoint(coordinate.getMinLongitude(), coordinate.getMinLatitude());
104             return getWKTString(geometry);
105         } else {
106             Geometry geometry = createLine(coordinate.getMinLongitude(), coordinate.getMinLatitude(), coordinate.getMaxLongitude(), coordinate.getMaxLatitude());
107             return getWKTString(geometry);
108         }
109     }
110 
111     /**
112      * <p>isValid.</p>
113      *
114      * @param coordinate a {@link fr.ifremer.dali.dto.CoordinateDTO} object.
115      * @return a boolean.
116      */
117     public static boolean isValid(CoordinateDTO coordinate) {
118         return coordinate != null && (
119                 (coordinate.getMinLongitude() != null && coordinate.getMaxLongitude() == null && coordinate.getMinLatitude() != null && coordinate.getMaxLatitude() == null)
120                         || (coordinate.getMinLongitude() != null && coordinate.getMaxLongitude() != null && coordinate.getMinLatitude() != null && coordinate.getMaxLatitude() != null)
121         );
122 
123     }
124 
125     /**
126      * <p>isPoint.</p>
127      *
128      * @param coordinate a {@link fr.ifremer.dali.dto.CoordinateDTO} object.
129      * @return a boolean.
130      */
131     public static boolean isPoint(CoordinateDTO coordinate) {
132 
133         if (coordinate.getMinLongitude() != null && coordinate.getMinLatitude() != null
134                 && coordinate.getMaxLongitude() == null && coordinate.getMaxLatitude() == null) {
135 
136             // coordinate has only min long/lat
137             return true;
138         }
139 
140         // true if min long/lat equals max log/lat
141         return coordinate.getMinLongitude() != null && coordinate.getMinLatitude() != null && coordinate.getMaxLongitude() != null && coordinate.getMaxLatitude() != null
142                 && Objects.equals(coordinate.getMinLongitude(), coordinate.getMaxLongitude()) && Objects.equals(coordinate.getMinLatitude(), coordinate.getMaxLatitude());
143 
144     }
145 
146     /**
147      * <p>equals.</p>
148      *
149      * @param source a {@link fr.ifremer.dali.dto.CoordinateDTO} object.
150      * @param target a {@link fr.ifremer.dali.dto.CoordinateDTO} object.
151      * @return a boolean.
152      */
153     public static boolean equals(CoordinateDTO source, CoordinateDTO target) {
154 
155         if (source == null && target == null) {
156             // assume both null are equals
157             return true;
158         } else if (source == null ^ target == null) {
159             // but if one is null, return false
160             return false;
161         }
162 
163         if (isPoint(source) && isPoint(target)) {
164             // if both are point, check only min long/lat
165             return Objects.equals(source.getMinLongitude(), target.getMinLongitude()) && Objects.equals(source.getMinLatitude(), target.getMinLatitude());
166         } else if (!isPoint(source) && !isPoint(target)) {
167             // check all values
168             return Objects.equals(source.getMinLongitude(), target.getMinLongitude()) && Objects.equals(source.getMinLatitude(), target.getMinLatitude())
169                     && Objects.equals(source.getMaxLongitude(), target.getMaxLongitude()) && Objects.equals(source.getMaxLatitude(), target.getMaxLatitude());
170         }
171 
172         // otherwise not equals
173         return false;
174 
175     }
176 
177     /**
178      * <p>equals.</p>
179      *
180      * @param source         a {@link fr.ifremer.dali.dto.CoordinateDTO} object.
181      * @param targetPosition a {@link java.lang.String} object.
182      * @return a boolean.
183      */
184     public static boolean equals(CoordinateDTO source, String targetPosition) {
185 
186         CoordinateDTO target = getCoordinate(targetPosition);
187 
188         return equals(source, target);
189     }
190 
191     public static String toString(CoordinateDTO coordinate) {
192         return coordinate == null
193                 ? "null"
194                 : String.format(
195                 "minLatitude: %s ; minLongitude: %s ; maxLatitude: %s ; maxLongitude: %s",
196                 coordinate.getMinLatitude(),
197                 coordinate.getMinLongitude(),
198                 coordinate.getMaxLatitude(),
199                 coordinate.getMaxLongitude()
200         );
201     }
202 
203     /**
204      * Calculate distance between the min and max coordinate in meters (in a WGS84 system)
205      * Only if the coordinate object is a line
206      *
207      * @param coordinate the coordinate object
208      * @return the distance in meter or null if error in transformation occurs
209      */
210     public static Double getDistanceInMeter(CoordinateDTO coordinate) {
211 
212         if (isValid(coordinate) && !isPoint(coordinate)) {
213 
214             Coordinate point1 = new Coordinate(coordinate.getMinLongitude(), coordinate.getMinLatitude());
215             Coordinate point2 = new Coordinate(coordinate.getMaxLongitude(), coordinate.getMaxLatitude());
216             return getDistanceInMeter(point1, point2);
217         }
218 
219         return null;
220     }
221 
222     /**
223      * Calculate distance between 2 coordinates in meters (in a WGS84 system)
224      *
225      * @param coordinate1 the first coordinate
226      * @param coordinate2 the second coordinate
227      * @return the distance in meter or null if error in transformation occurs
228      */
229     public static Double getDistanceInMeter(Coordinate coordinate1, Coordinate coordinate2) {
230 
231         Double distance = null;
232         try {
233             distance = JTS.orthodromicDistance(coordinate1, coordinate2, DefaultGeographicCRS.WGS84);
234         } catch (TransformException e) {
235             LOG.error(String.format("Can't calculate distance between %s and %s", coordinate1, coordinate2), e);
236         }
237         return distance;
238     }
239 
240 }