Skip to contentMethod: getNorthWest()
1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * blueMarine III: Semantic DAM
5: * http://tidalwave.it/projects/bluemarine3
6: *
7: * Copyright (C) 2024 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *************************************************************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12: * You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/bluemarine3-src
22: * git clone https://github.com/tidalwave-it/bluemarine3-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.geo.impl;
27:
28: import jakarta.annotation.Nonnull;
29: import java.util.Optional;
30: import it.tidalwave.geo.Area;
31: import it.tidalwave.geo.Coordinates;
32: import it.tidalwave.geo.RectangularArea;
33: import it.tidalwave.util.As;
34: import lombok.EqualsAndHashCode;
35: import lombok.Getter;
36: import lombok.RequiredArgsConstructor;
37: import lombok.experimental.Delegate;
38: import static java.lang.Math.*;
39:
40: /***************************************************************************************************************************************************************
41: *
42: * @author Fabrizio Giudici
43: *
44: **************************************************************************************************************************************************************/
45: @RequiredArgsConstructor @Getter @EqualsAndHashCode(exclude = "asDelegate")
46: public class DefaultRectangularArea implements RectangularArea
47: {
48: public static final RectangularArea EMPTY = new DefaultRectangularArea();
49:
50: @Delegate @SuppressWarnings("this-escape")
51: private final As asDelegate = As.forObject(this);
52:
53: @Getter
54: private final boolean empty;
55:
56: private final Coordinates northWest;
57:
58: private final Coordinates southEast;
59:
60: /***********************************************************************************************************************************************************
61: *
62: **********************************************************************************************************************************************************/
63: private DefaultRectangularArea()
64: {
65: this(true, Coordinates.of(0, 0), Coordinates.of(0, 0)); // dummy
66: }
67:
68: /***********************************************************************************************************************************************************
69: *
70: **********************************************************************************************************************************************************/
71: public DefaultRectangularArea (@Nonnull final Coordinates northWest, @Nonnull final Coordinates southEast)
72: {
73: this(false, northWest, southEast);
74: }
75:
76: /***********************************************************************************************************************************************************
77: * {@inheritDoc}
78: **********************************************************************************************************************************************************/
79: @Nonnull
80: public Optional<Coordinates> getNorthWest()
81: {
82:• return empty ? Optional.empty() : Optional.of(northWest);
83: }
84:
85: /***********************************************************************************************************************************************************
86: * {@inheritDoc}
87: **********************************************************************************************************************************************************/
88: @Nonnull
89: public Optional<Coordinates> getSouthEast()
90: {
91: return empty ? Optional.empty() : Optional.of(southEast);
92: }
93:
94: /***********************************************************************************************************************************************************
95: * {@inheritDoc}
96: **********************************************************************************************************************************************************/
97: @Nonnull
98: public Optional<Coordinates> getCenter()
99: {
100: return empty ? Optional.empty()
101: : Optional.of(Coordinates.of((northWest.getLatitude() + southEast.getLatitude()) / 2,
102: (northWest.getLongitude() + southEast.getLongitude()) / 2));
103: }
104:
105: /***********************************************************************************************************************************************************
106: * {@inheritDoc}
107: **********************************************************************************************************************************************************/
108: @Nonnull
109: public RectangularArea including (@Nonnull final Coordinates coordinates)
110: {
111: return empty ? new DefaultRectangularArea(coordinates, coordinates)
112: : new DefaultRectangularArea(moreToTheNorthWest(northWest, coordinates), moreToTheSouthEast(southEast, coordinates));
113: }
114:
115: /***********************************************************************************************************************************************************
116: * {@inheritDoc}
117: **********************************************************************************************************************************************************/
118: @Nonnull
119: public RectangularArea including (@Nonnull final Area that)
120: {
121: if (empty && that instanceof final RectangularArea thatR)
122: {
123: return thatR;
124: }
125:
126: if (that instanceof final RectangularArea thatR)
127: {
128: return thatR.isEmpty() ? this : new DefaultRectangularArea(moreToTheNorthWest(northWest, thatR.getNorthWest().orElseThrow()),
129: moreToTheSouthEast(southEast, thatR.getSouthEast().orElseThrow()));
130: }
131:
132: throw new IllegalArgumentException("" + that); // TODO for other area types, that at the moment aren't there
133: }
134:
135: /***********************************************************************************************************************************************************
136: * {@inheritDoc}
137: **********************************************************************************************************************************************************/
138: @Override
139: public String toString()
140: {
141: return isEmpty() ? "DefaultRectangularArea(empty)"
142: : String.format("DefaultRectangularArea(nw=%s, se=%s)", northWest, southEast);
143: }
144:
145: /***********************************************************************************************************************************************************
146: * {@return the point more to the north-west between two points}.
147: * @param c1 the former point
148: * @param c2 the latter point
149: **********************************************************************************************************************************************************/
150: @Nonnull
151: private static Coordinates moreToTheNorthWest (@Nonnull final Coordinates c1, @Nonnull final Coordinates c2)
152: {
153: return Coordinates.of(max(c1.getLatitude(), c2.getLatitude()), min(c1.getLongitude(), c2.getLongitude()));
154: }
155:
156: /***********************************************************************************************************************************************************
157: * {@return the point more to the south-east between two points}.
158: * @param c1 the former point
159: * @param c2 the latter point
160: **********************************************************************************************************************************************************/
161: @Nonnull
162: private static Coordinates moreToTheSouthEast (@Nonnull final Coordinates c1, @Nonnull final Coordinates c2)
163: {
164: // FIXME: doesn't work around line of change of date
165: return Coordinates.of(min(c1.getLatitude(), c2.getLatitude()), max(c1.getLongitude(), c2.getLongitude()));
166: }
167: }
168: