1
2 package hep.wired.heprep.projection;
3
4 import java.awt.geom.*;
5 import java.util.*;
6
7 import org.jdom.Element;
8
9 import org.freehep.xml.io.XMLIO;
10 import org.freehep.xml.io.XMLIOManager;
11
12 import hep.wired.feature.Rotateable2D;
13 import hep.wired.feature.Transformable2D;
14 import hep.wired.feature.Rotateable3D;
15 import hep.wired.feature.Transformable3D;
16 import hep.wired.feature.Resetable;
17 import hep.wired.services.ViewPort;
18 import hep.wired.heprep.services.Projection;
19 import hep.wired.util.Matrix3D;
20
21 /***
22 * 3D parallel projection of (X,Y,Z) into (U,V,W).
23 *
24 * @author Mark Donszelmann
25 * @version $Id: ParallelProjection.java 2074 2005-07-20 06:22:09Z duns $
26 */
27
28 public abstract class ParallelProjection extends AbstractProjection
29 implements Rotateable2D, Transformable2D,
30 Rotateable3D, Transformable3D,
31 Resetable {
32
33
34 private final static double defaultScaleFactor = 0.001;
35
36 protected Matrix3D matrix;
37 protected Matrix3D resetMatrix;
38
39 public static class XY extends ParallelProjection {
40 public XY() {
41 super();
42 }
43
44 protected XY(Matrix3D matrix, Matrix3D resetMatrix) {
45 super(matrix, resetMatrix);
46 }
47
48 public Projection copy() {
49 return new XY(matrix, resetMatrix);
50 }
51 }
52
53 public static class ZX extends ParallelProjection {
54 public ZX() {
55 super(new Matrix3D(0, 1, 0,
56 0, 0, 1,
57 1, 0, 0,
58 0, 0, 0));
59 }
60
61 protected ZX(Matrix3D matrix, Matrix3D resetMatrix) {
62 super(matrix, resetMatrix);
63 }
64
65 public Projection copy() {
66 return new ZX(matrix, resetMatrix);
67 }
68 }
69
70 public static class ZY extends ParallelProjection {
71 public ZY() {
72 super(new Matrix3D( 0, 0,-1,
73 0, 1, 0,
74 1, 0, 0,
75 0, 0, 0));
76 }
77
78 protected ZY(Matrix3D matrix, Matrix3D resetMatrix) {
79 super(matrix, resetMatrix);
80 }
81
82 public Projection copy() {
83 return new ZY(matrix, resetMatrix);
84 }
85 }
86
87 public static class XZ extends ParallelProjection {
88 public XZ() {
89 super(new Matrix3D(1, 0, 0,
90 0, 0, -1,
91 0, 1, 0,
92 0, 0, 0));
93 }
94
95 protected XZ(Matrix3D matrix, Matrix3D resetMatrix) {
96 super(matrix, resetMatrix);
97 }
98
99 public Projection copy() {
100 return new XZ(matrix, resetMatrix);
101 }
102 }
103
104 public static class YZ extends ParallelProjection {
105 public YZ() {
106 super(new Matrix3D( 0, 0, 1,
107 1, 0, 0,
108 0, 1, 0,
109 0, 0, 0));
110 }
111
112 protected YZ(Matrix3D matrix, Matrix3D resetMatrix) {
113 super(matrix, resetMatrix);
114 }
115
116 public Projection copy() {
117 return new YZ(matrix, resetMatrix);
118 }
119 }
120
121 /***
122 * Creates a 3D parallel projection.
123 */
124 protected ParallelProjection() {
125 this(new Matrix3D());
126 }
127
128 protected ParallelProjection(Matrix3D matrix) {
129 this(matrix, matrix);
130 this.matrix.scale(defaultScaleFactor, defaultScaleFactor, defaultScaleFactor);
131 this.resetMatrix.scale(defaultScaleFactor, defaultScaleFactor, defaultScaleFactor);
132 }
133
134 /***
135 * Used for cloning
136 */
137 protected ParallelProjection(Matrix3D matrix, Matrix3D resetMatrix) {
138 super();
139 this.matrix = (Matrix3D)matrix.clone();
140 this.resetMatrix = (Matrix3D)resetMatrix.clone();
141 }
142
143 public String getFormula() {
144 return "(u,v,w) = "+
145 "m00*x + m01*y + m02*z + m03, "+
146 "m10*x + m11*y + m12*z + m13, "+
147 "m20*x + m21*y + m22*z + m23";
148 }
149
150 public double[] transform(double[] xyz) {
151 return matrix.transform(xyz, false);
152 }
153
154 public double[][] transform(double[][] xyz, int n) {
155 return matrix.transform(xyz, n, false);
156 }
157
158 public double[] deltaTransform(double[] xyz) {
159 return matrix.transform(xyz, true);
160 }
161
162 public double[] inverseTransform(double[] uvw) throws UnsupportedOperationException {
163 try {
164 Matrix3D inverse = matrix.createInverse();
165 return inverse.transform(uvw, false);
166 } catch (NoninvertibleTransformException e) {
167 throw new UnsupportedOperationException(e.getMessage());
168 }
169 }
170
171 public double[] inverseDeltaTransform(double[] uvw) throws UnsupportedOperationException {
172 try {
173 Matrix3D inverse = matrix.createInverse();
174 return inverse.transform(uvw, true);
175 } catch (NoninvertibleTransformException e) {
176 throw new UnsupportedOperationException(e.getMessage());
177 }
178 }
179
180 public String toString() {
181 return super.toString()+" : \n"+matrix.toString();
182 }
183
184
185 public void rotate(double theta, double nx, double ny, double nz) {
186 matrix.rotate(theta, nx, ny, nz);
187 }
188
189
190 public void rotate(double theta) {
191 rotate(theta, 0, 0, 1);
192 }
193
194
195 public double[] getModelTranslation(double[] uvw, ViewPort viewPort) {
196 uvw = viewPort.inverseDeltaTransform(uvw);
197 return inverseDeltaTransform(uvw);
198 }
199
200 public double[] getScreenTranslation(double[] xyz, ViewPort viewPort) {
201 xyz = deltaTransform(xyz);
202 return viewPort.deltaTransform(xyz);
203 }
204
205
206 public void scale(double s) {
207 scale(s, s, s);
208 }
209
210 public void setScale(double s) {
211 setScale(s, s, s);
212 }
213
214 public void scale(double sx, double sy, double sz) {
215 matrix.scale(sx, sy, sz);
216 }
217
218 public void setScale(double sx, double sy, double sz) {
219 double[] s = getScale();
220 matrix.scale(sx/s[X], sy/s[Y], sz/s[Z]);
221 }
222
223 public double[] getScale() {
224 return new double[] {matrix.getScaleX(), matrix.getScaleY(), matrix.getScaleZ()};
225 }
226
227 public void translate(double tx, double ty, double tz) {
228 matrix.modelTranslate(tx, ty, tz);
229 }
230
231 public void setTranslate(double tx, double ty, double tz) {
232 double[] t = getTranslate();
233 matrix.modelTranslate(tx - t[X], ty - t[Y], tz - t[Z]);
234 }
235
236 public double[] getTranslate() {
237 return inverseDeltaTransform(new double[] {matrix.getTranslateX(), matrix.getTranslateY(), matrix.getTranslateZ()});
238 }
239
240
241 public void scale(double sx, double sy) {
242 scale(sx, sy, 1);
243 }
244
245 public void setScale(double sx, double sy) {
246 setScale(sx, sy, matrix.getScaleZ());
247 }
248
249 /***
250 * Shears the viewpoint. Preconcatenates with the matrix:
251 * <pre>
252 * [ 1 shx 0 0 ]
253 * [ shy 1 0 0 ]
254 * [ 0 0 1 0 ]
255 * [ 0 0 0 1 ]
256 * </pre>
257 */
258 public void shear(double shx, double shy) {
259 matrix.shear(shx, shy);
260 }
261
262 public void translate(double tx, double ty) {
263 translate(tx, ty, 0);
264 }
265
266 public void setTranslate(double tx, double ty) {
267 setTranslate(tx, ty, matrix.getTranslateZ());
268 }
269
270
271 public Object reset(Object newState) {
272 Object oldState = matrix.clone();
273 matrix = (newState == null) ? (Matrix3D)resetMatrix.clone() : (Matrix3D)newState;
274 return oldState;
275 }
276
277
278
279
280 public void save(XMLIOManager xmlioManager,
281 org.jdom.Element nodeEl) {
282 super.save(xmlioManager, nodeEl);
283 nodeEl.addContent(xmlioManager.save(matrix));
284 nodeEl.addContent(xmlioManager.save(resetMatrix));
285 }
286
287 public void restore(XMLIOManager xmlioManager,
288 org.jdom.Element nodeEl) {
289 super.restore(xmlioManager, nodeEl);
290 Iterator i=nodeEl.getChildren().iterator();
291 matrix = (Matrix3D)xmlioManager.restore((Element)i.next());
292 resetMatrix = (Matrix3D)xmlioManager.restore((Element)i.next());
293 }
294 }
295