| IsometryData.java |
1 /****************************************************************************
2 * This demo file is part of yFiles for Java 2.14.
3 * Copyright (c) 2000-2017 by yWorks GmbH, Vor dem Kreuzberg 28,
4 * 72070 Tuebingen, Germany. All rights reserved.
5 *
6 * yFiles demo files exhibit yFiles for Java functionalities. Any redistribution
7 * of demo files in source code or binary form, with or without
8 * modification, is not permitted.
9 *
10 * Owners of a valid software license for a yFiles for Java version that this
11 * demo is shipped with are allowed to use the demo source code as basis
12 * for their own yFiles for Java powered applications. Use of such programs is
13 * governed by the rights and conditions as set out in the yFiles for Java
14 * license agreement.
15 *
16 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19 * NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 ***************************************************************************/
28 package demo.view.isometry;
29
30 import java.awt.geom.Rectangle2D;
31
32 /**
33 * The class stores the height, width and depth of a solid figure. This data is used to get its bounds in the view space
34 * and the bounds of its base area used in the layout space.
35 */
36 public class IsometryData implements Cloneable {
37 // Matrix to transform points from the layout space into the view space.
38 public static final double M_TO_VIEW_11 = Math.sqrt(3) * 0.5;
39 public static final double M_TO_VIEW_12 = M_TO_VIEW_11;
40 public static final double M_TO_VIEW_21 = -0.5;
41 public static final double M_TO_VIEW_22 = 0.5;
42
43 // Matrix to transform points from the view space into the layout space.
44 public static final double M_TO_LAYOUT_11 = 1 / Math.sqrt(3);
45 public static final double M_TO_LAYOUT_12 = -1;
46 public static final double M_TO_LAYOUT_21 = M_TO_LAYOUT_11;
47 public static final double M_TO_LAYOUT_22 = -M_TO_LAYOUT_12;
48
49 // Indices for the corners of the bounding box.
50 public static final int C0_X = 0; // lower left
51 public static final int C0_Y = 1;
52 public static final int C1_X = 2; // lower front
53 public static final int C1_Y = 3;
54 public static final int C2_X = 4; // lower right
55 public static final int C2_Y = 5;
56 public static final int C3_X = 6; // lower back
57 public static final int C3_Y = 7;
58 public static final int C4_X = 8; // upper left
59 public static final int C4_Y = 9;
60 public static final int C5_X = 10; // upper front
61 public static final int C5_Y = 11;
62 public static final int C6_X = 12; // upper right
63 public static final int C6_Y = 13;
64 public static final int C7_X = 14; // upper back
65 public static final int C7_Y = 15;
66
67 private double width;
68 private double height;
69 private double depth;
70
71 private boolean isHorizontal;
72
73 /**
74 * Creates an instance with the given dimensions.
75 */
76 public IsometryData(final double width, final double depth, final double height, final boolean isHorizontal) {
77 this.width = width;
78 this.depth = depth;
79 this.height = height;
80 this.isHorizontal = isHorizontal;
81 }
82
83 /**
84 * Returns the width of the solid figure.
85 */
86 public double getWidth() {
87 return width;
88 }
89
90 /**
91 * Sets the width of the solid figure.
92 */
93 public void setWidth(final double width) {
94 this.width = width;
95 }
96
97 /**
98 * Returns the depth of the solid figure.
99 */
100 public double getDepth() {
101 return depth;
102 }
103
104 /**
105 * Sets the depth of the solid figure.
106 */
107 public void setDepth(final double depth) {
108 this.depth = depth;
109 }
110
111 /**
112 * Returns the height of the solid figure.
113 */
114 public double getHeight() {
115 return height;
116 }
117
118 /**
119 * Sets the height of the solid figure.
120 */
121 public void setHeight(final double height) {
122 this.height = height;
123 }
124
125 /**
126 * Determines whether or no the base of the solid figure is horizontal in layout space.
127 * This is important for labels that may be rotated during layout.
128 */
129 public boolean isHorizontal() {
130 return isHorizontal;
131 }
132
133 /**
134 * Specifies whether or no the base of the solid figure is horizontal in layout space.
135 * This is important for labels that may be rotated during layout.
136 */
137 public void setHorizontal(boolean horizontal) {
138 isHorizontal = horizontal;
139 }
140
141 /**
142 * Calculates the bounds of the solid figure in the view space.
143 *
144 * @param bounds the calculated bounds
145 */
146 public void calculateViewBounds(final Rectangle2D bounds) {
147 final double[] corners = new double[16];
148 calculateCorners(corners);
149 calculateViewBounds(corners, bounds);
150 }
151
152 /**
153 * Calculates the bounds of the solid figure in the view space.
154 *
155 * @param corners the corners of the projection of the bounds of solid figure into the view space
156 * @param bounds the calculated bounds
157 */
158 public static void calculateViewBounds(final double[] corners, final Rectangle2D bounds) {
159 double minX = corners[C0_X];
160 double minY = corners[C0_Y];
161 double maxX = corners[C0_X];
162 double maxY = corners[C0_Y];
163 for (int i = 2; i < corners.length; i += 2) {
164 minX = Math.min(minX, corners[i]);
165 minY = Math.min(minY, corners[i + 1]);
166 maxX = Math.max(maxX, corners[i]);
167 maxY = Math.max(maxY, corners[i + 1]);
168 }
169 bounds.setFrame(minX, minY, maxX - minX, maxY - minY);
170 }
171
172 /**
173 * Calculates the corners of the projection of the bounds of solid figure into the view space.
174 *
175 * @param corners the calculated corners.
176 */
177 public void calculateCorners(final double[] corners) {
178 corners[C0_X] = 0;
179 corners[C0_Y] = 0;
180
181 corners[C1_X] = toViewX(getWidth(), 0);
182 corners[C1_Y] = toViewY(getWidth(), 0);
183
184 corners[C2_X] = toViewX(getWidth(), getDepth());
185 corners[C2_Y] = toViewY(getWidth(), getDepth());
186
187 corners[C3_X] = toViewX(0, getDepth());
188 corners[C3_Y] = toViewY(0, getDepth());
189
190 for (int i = 0; i < 8; i += 2) {
191 corners[i + 8] = corners[i];
192 corners[i + 9] = corners[i + 1] - getHeight();
193 }
194 }
195
196 /**
197 * Transforms the given point from the layout space into the view space.
198 *
199 * @param layoutX x-coordinate in layout space
200 * @param layoutY y-coordinate in layout space
201 * @return x-coordinate in view space
202 */
203 static double toViewX(final double layoutX, final double layoutY) {
204 return M_TO_VIEW_11 * layoutX + M_TO_VIEW_12 * layoutY;
205 }
206
207 /**
208 * Transforms the given point from the layout space into the view space.
209 *
210 * @param layoutX x-coordinate in layout space
211 * @param layoutY y-coordinate in layout space
212 * @return y-coordinate in view space
213 */
214 static double toViewY(final double layoutX, final double layoutY) {
215 return M_TO_VIEW_21 * layoutX + M_TO_VIEW_22 * layoutY;
216 }
217
218 /**
219 * Transforms the given point from the view space into the layout space.
220 *
221 * @param viewX x-coordinate in view space
222 * @param viewY y-coordinate in view space
223 * @return x-coordinate in layout space
224 */
225 static double toLayoutX(final double viewX, final double viewY) {
226 return M_TO_LAYOUT_11 * viewX + M_TO_LAYOUT_12 * viewY;
227 }
228
229 /**
230 * Transforms the given point from the view space into the layout space.
231 *
232 * @param viewX x-coordinate in view space
233 * @param viewY y-coordinate in view space
234 * @return y-coordinate in layout space
235 */
236 static double toLayoutY(final double viewX, final double viewY) {
237 return M_TO_LAYOUT_21 * viewX + M_TO_LAYOUT_22 * viewY;
238 }
239
240 /**
241 * Translates the given corner to the given location, so that the upper left location of the bounds of the given
242 * corners is on the given location.
243 *
244 * @param x x-coordinate of the location where the corners should be moved to
245 * @param y y-coordinate of the location where the corners should be moved to
246 * @param corners corners to be moved
247 */
248 public static void moveTo(final double x, final double y, final double[] corners) {
249 // Calculate the upper left location of the bounds of the given corners.
250 double minX = corners[C0_X];
251 double minY = corners[C0_Y];
252 for (int i = 2; i < corners.length; i += 2) {
253 minX = Math.min(minX, corners[i]);
254 minY = Math.min(minY, corners[i + 1]);
255 }
256
257 // Move the corners to the given location.
258 final double dx = x - minX;
259 final double dy = y - minY;
260 for (int i = 0; i < corners.length; i += 2) {
261 corners[i] += dx;
262 corners[i + 1] += dy;
263 }
264 }
265
266 public Object clone () throws CloneNotSupportedException {
267 return super.clone();
268 }
269 }
270