source: trunk/src/org/expeditee/core/bounds/EllipticalBounds.java@ 1415

Last change on this file since 1415 was 1415, checked in by bln4, 5 years ago

Renamed Frame.getItems() to Frame.getSortedItems() to better represent its functionality.

-> org.apollo.ApolloGestureActions
-> org.apollo.ApolloSystem
-> org.expeditee.actions.Actions
-> org.expeditee.actions.Debug
-> org.expeditee.actions.ExploratorySearchActions
-> org.expeditee.actions.JfxBrowserActions
-> org.expeditee.actions.Misc
-> org.expeditee.actions.Navigation
-> org.expeditee.actions.ScriptBase
-> org.expeditee.actions.Simple
-> org.expeditee.agents.ComputeTree
-> org.expeditee.agents.CopyTree
-> org.expeditee.agents.DisplayComet
-> org.expeditee.agents.DisplayTree
-> org.expeditee.agents.DisplayTreeLeaves
-> org.expeditee.agents.GraphFramesetLinks
-> org.expeditee.agents.TreeProcessor
-> org.expeditee.gio.gesture.StandardGestureActions
-> org.expeditee.gui.DisplayController
-> org.expeditee.gui.FrameCreator
-> org.expeditee.gui.FrameIO
-> org.expeditee.io.DefaultTreeWriter
-> org.expeditee.io.JavaWriter
-> org.expeditee.io.PDF2Writer
-> org.expeditee.io.TXTWriter
-> org.expeditee.io.WebParser
-> org.expeditee.io.flowlayout.XGroupItem
-> org.expeditee.items.Dot
-> org.expeditee.items.Item
-> org.expeditee.items.ItemUtils
-> org.expeditee.network.FrameShare
-> org.expeditee.stats.TreeStats


Created ItemsList class to wrap ArrayList<Item>. Frames now use this new class to store its body list (used for display) as well as its primaryBody and surrogateBody.

-> org.expeditee.agents.Format
-> org.expeditee.agents.HFormat
-> org.expeditee.gio.gesture.StandardGestureActions
-> org.expeditee.gui.Frame
-> org.expeditee.gui.FrameUtils


Refactorted Frame.setResort(bool) to Frame.invalidateSorted() to better function how it is intended to with a more accurate name.

-> org.expeditee.agents.Sort


When writing out .exp files and getting attributes to respond to LEFT + RIGHT click, boolean items are by default true. This has always been the case. An ammendment to this is that defaults can now be established.
Also added 'EnterClick' functionality. If cursored over a item with this property and you press enter, it acts as if you have clicked on it instead.

-> org.expeditee.assets.resources-public.framesets.authentication.1.exp to 6.exp
-> org.expeditee.gio.gesture.StandardGestureActions
-> org.expeditee.gio.input.KBMInputEvent
-> org.expeditee.gio.javafx.JavaFXConversions
-> org.expeditee.gio.swing.SwingConversions
-> org.expeditee.gui.AttributeUtils
-> org.expeditee.io.Conversion
-> org.expeditee.io.DefaultFrameWriter
-> org.expeditee.items.Item


Fixed a bug caused by calling Math.abs on Integer.MIN_VALUE returning unexpected result. Due to zero being a thing, you cannot represent Math.abs(Integer.MIN_VALUE) in a Integer object. The solution is to use Integer.MIN_VALUE + 1 instead of Integer.MIN_VALUE.

-> org.expeditee.core.bounds.CombinationBounds
-> org.expeditee.io.flowlayout.DimensionExtent


Recoded the contains function in EllipticalBounds so that intersection tests containing circles work correctly.

-> org.expeditee.core.bounds.EllipticalBounds


Added toString() to PolygonBounds to allow for useful printing during debugging.

-> org.expeditee.core.bounds.PolygonBounds

Implemented Surrogate Mode!

-> org.expeditee.encryption.io.EncryptedExpReader
-> org.expeditee.encryption.io.EncryptedExpWriter
-> org.expeditee.encryption.items.surrogates.EncryptionDetail
-> org.expeditee.encryption.items.surrogates.Label
-> org.expeditee.gui.FrameUtils
-> org.expeditee.gui.ItemsList
-> org.expeditee.items.Item
-> org.expeditee.items.Text


???? Use Integer.MAX_VALUE cast to a float instead of Float.MAX_VALUE. This fixed some bug which I cannot remember.

-> org.expeditee.gio.TextLayoutManager
-> org.expeditee.gio.swing.SwingTextLayoutManager


Improved solution for dealing with the F10 key taking focus away from Expeditee due to it being a assessibility key.

-> org.expeditee.gio.swing.SwingInputManager


Renamed variable visibleItems in FrameGraphics.paintFrame to itemsToPaintCanditates to better represent functional intent.

-> org.expeditee.gui.FrameGraphics


Improved checking for if personal resources exist before recreating them

-> org.expeditee.gui.FrameIO


Repeated messages to message bay now have a visual feedback instead of just a beep. This visual feedback is in the form of a count of the amount of times it has repeated.

-> org.expeditee.gui.MessageBay


Updated comment on the Vector class to explain what vectors are.

-> org.expeditee.gui.Vector


Added constants to represent all of the property keys in DefaultFrameReader and DefaultFrameWriter.

-> org.expeditee.io.DefaultFrameReader
-> org.expeditee.io.DefaultFrameWriter


Updated the KeyList setting to be more heirarcial with how users will store their Secrets.

-> org.expeditee.settings.identity.secrets.KeyList

File size: 7.9 KB
Line 
1package org.expeditee.core.bounds;
2
3import org.expeditee.Util;
4import org.expeditee.core.Dimension;
5import org.expeditee.core.Line;
6import org.expeditee.core.Point;
7
8/**
9 * A bounds in the shape of an ellipse.
10 *
11 * @author cts16
12 */
13public class EllipticalBounds extends Bounds {
14
15 /** The location of the centre of the ellipse. */
16 private Point _centre;
17 /** The diameters of the ellipse in the x- and y-dimension. */
18 private Dimension _diameters;
19
20 /** Standard constructor. */
21 public EllipticalBounds(Point centre, Dimension diameters)
22 {
23 setCentre(centre);
24 setDiameters(diameters);
25 }
26
27 /** Constructor for a circular bounds. */
28 public EllipticalBounds(Point centre, int diameter)
29 {
30 this(centre, new Dimension(diameter, diameter));
31 }
32
33 /** Copy constructor. */
34 public EllipticalBounds(EllipticalBounds other)
35 {
36 setCentre(other._centre);
37 setDiameters(other._diameters);
38 }
39
40 /** Sets the location of the centre of this elliptical bounds. */
41 public void setCentre(Point centre)
42 {
43 // Control referential access to private variables
44 _centre = new Point(centre);
45 }
46
47 /** Sets the size of the diameters of this elliptical bounds. */
48 public void setDiameters(Dimension diameters)
49 {
50 // Control referential access to private variables
51 _diameters = new Dimension(diameters);
52
53 // Diameters must be positive
54 _diameters.absolve();
55 }
56
57 /** Gets the centre of the elliptical bounds. */
58 public Point getCentre()
59 {
60 // Control referential access to private variables
61 return _centre.clone();
62 }
63
64 /** Gets the size of the diameters of the elliptical bounds. */
65 public Dimension getDiameters()
66 {
67 // Control referential access to private variables
68 return _diameters.clone();
69 }
70
71 @Override
72 public boolean contains(int x, int y) {
73 // If the ellipse is degenerate then it can't contain anything
74 if (_diameters.getArea() == 0) return false;
75
76 double deltaXSq = Math.pow(x - _centre.getX(), 2);
77 double deltaYSq = Math.pow(y - _centre.getY(), 2);
78 double minorAxisSq = Math.pow(Math.min(_diameters.height, _diameters.width) / 2, 2);
79 double majorAxisSq = Math.pow(Math.max(_diameters.height, _diameters.width) / 2, 2);
80 double result = (deltaXSq / majorAxisSq) + (deltaYSq / minorAxisSq);
81 return result <= 1.0f;
82 }
83
84 @Override
85 public int getMaxX()
86 {
87 return _centre.getX() + (_diameters.width / 2 + _diameters.width % 2);
88 }
89
90 @Override
91 public int getMinX()
92 {
93 return _centre.getX() -(_diameters.width / 2 + _diameters.width % 2);
94 }
95
96 @Override
97 public int getMaxY()
98 {
99 return _centre.getY() + (_diameters.height / 2 + _diameters.height % 2);
100 }
101
102 @Override
103 public int getMinY()
104 {
105 return _centre.getY() - (_diameters.height / 2 + _diameters.height % 2);
106 }
107
108 @Override
109 public EllipticalBounds translate(int x, int y)
110 {
111 _centre.add(x, y);
112
113 return this;
114 }
115
116 @Override
117 public boolean equals(Bounds other) {
118 if (other instanceof EllipticalBounds) {
119 EllipticalBounds e = (EllipticalBounds) other;
120 return e._centre.equals(this._centre) && e._diameters.equals(this._diameters);
121 }
122 return false;
123 }
124
125 @Override
126 public boolean intersects(AxisAlignedBoxBounds other) {
127 // Treat the box as a polygon
128 return intersects(other.getPolygon());
129 }
130
131 @Override
132 public boolean intersects(CombinationBounds other) {
133 // Defer to the CombinationBounds routine
134 return other.intersects(this);
135 }
136
137 @Override
138 public boolean intersects(EllipticalBounds other) {
139 // TODO: Implement. cts16
140 System.err.println("Unimplemented method: EllipticalBounds.intersects(EllipticalBounds)");
141 return false;
142 }
143
144 @Override
145 public boolean intersects(PolygonBounds other)
146 {
147 // If any point in the polygon is inside the ellipse then they intersect
148 for (Point p : other.getVertices()) {
149 if (contains(p)) return true;
150 }
151
152 // If no polygon point is contained, may still intersect polygon boundary lines
153 for (Line line : other.getBorderLines()) {
154 if (isIntersectedByLine(line)) return true;
155 }
156
157 return false;
158 }
159
160 @Override
161 public double getArea()
162 {
163 // Area = pi * r_x * r_y
164 // (dividing by 4.0 because using diameters instead of radii)
165 return Math.PI * _diameters.getArea() / 4.0;
166 }
167
168 @Override
169 public boolean perimeterContains(Point p, double error)
170 {
171 // If the given point is null, we can't test
172 if (p == null) return false;
173
174 // Find the distance from the centre of the ellipse to the given point
175 double pRadialDistance = Point.distanceBetween(p, _centre);
176
177 // Find the distance to the ellipse border in the same direction
178 double borderRadialDistance = radialDistanceAtAngle(getAngleToPoint(p));
179
180 // If the difference between these two distances is within error then we are on the perimeter
181 return Math.abs(borderRadialDistance - pRadialDistance) <= error;
182
183 }
184
185 @Override
186 public boolean completelyContains(AxisAlignedBoxBounds other)
187 {
188 // Can't contain nothing
189 if (other == null) return false;
190
191 // It is sufficient to test if all four corners are contained
192 Point[] corners = other.getCorners();
193 for (Point corner : corners) {
194 if (!contains(corner)) return false;
195 }
196
197 return true;
198 }
199
200 @Override
201 public boolean completelyContains(CombinationBounds other)
202 {
203 // Can't contain nothing
204 if (other == null) return false;
205
206 // Must contain all sub-bounds
207 for (Bounds bound : other._bounds) {
208 if (!completelyContains(bound)) return false;
209 }
210
211 return true;
212 }
213
214 @Override
215 public boolean completelyContains(EllipticalBounds other)
216 {
217 // TODO: Implement. cts16
218 System.err.println("Unimplemented method: EllipticalBounds.completelyContains(EllipticalBounds)");
219 return false;
220 }
221
222 @Override
223 public boolean completelyContains(PolygonBounds other)
224 {
225 // Can't contain nothing
226 if (other == null) return false;
227
228 // It is sufficient to test if all vertices are contained
229 Point[] vertices = other.getVertices();
230 for (Point vertex : vertices) {
231 if (!contains(vertex)) return false;
232 }
233
234 return true;
235 }
236
237 /** Gets the distance to the border of the ellipse at a given angle. */
238 public double radialDistanceAtAngle(double angle)
239 {
240 double xComponent = (_diameters.width / 2.0) * Math.cos(angle);
241 double yComponent = (_diameters.height / 2.0) * Math.sin(angle);
242 return Math.sqrt(xComponent * xComponent + yComponent * yComponent);
243 }
244
245 /** Gets the bearing angle from the centre of the ellipse to a given point. */
246 public double getAngleToPoint(Point p)
247 {
248 if (p == null) return Double.NaN;
249
250 Point pRel = Point.difference(p, _centre);
251 return Math.atan2(pRel.getY(), pRel.getX());
252 }
253
254 /** Whether the given line intersects the perimeter of this ellipse. */
255 public boolean isIntersectedByLine(Line line)
256 {
257 // Can't intersect with nothing
258 if (line == null) return false;
259
260 // Get the t-values at the points of intersections (if there are any)
261 double r_x = _diameters.width / 2.0;
262 double r_y = _diameters.height / 2.0;
263 Point lineStartRel = Point.difference(line.getFirstEnd(), _centre);
264 double x_0 = lineStartRel.getX();
265 double y_0 = lineStartRel.getY();
266 double x_d = line.deltaX();
267 double y_d = line.deltaY();
268 double r_x_squared = r_x * r_x;
269 double r_y_squared = r_y * r_y;
270 double x_0_squared = x_0 * x_0;
271 double y_0_squared = y_0 * y_0;
272 double x_d_squared = x_d * x_d;
273 double y_d_squared = y_d * y_d;
274 double[] roots = Util.quadraticEquation(
275 x_d_squared * r_y_squared + y_d_squared * r_x_squared,
276 2 * (r_y_squared * x_0 * x_d + r_x_squared * y_0 * y_d),
277 r_y_squared * x_0_squared + r_x_squared * y_0_squared - r_x_squared * r_y_squared
278 );
279
280 // No roots, no intersection
281 if (roots == null) return false;
282
283 // See if any of the roots is inside the line segment
284 for (double root : roots) {
285 if (0.0 <= root && root <= 1.0) return true;
286 }
287
288 return false;
289 }
290
291 /** Creates a polygonal approximation of this ellipse. */
292 public PolygonBounds getPolygon(int nSegments)
293 {
294 return PolygonBounds.fromEllipse(this, nSegments);
295 }
296
297 @Override
298 public EllipticalBounds clone()
299 {
300 return new EllipticalBounds(this);
301 }
302
303}
Note: See TracBrowser for help on using the repository browser.