View Javadoc

1   // Copyright 2004-2005, FreeHEP.
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      // FIXME WIRED-242, take from preferences
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 // Rotateable3D
185     public void rotate(double theta, double nx, double ny, double nz) {
186         matrix.rotate(theta, nx, ny, nz);
187     }
188 
189 // Rotateable2D
190     public void rotate(double theta) {
191         rotate(theta, 0, 0, 1);
192     }    
193 
194 // Translateable
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 // Transformable3D
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 // Transformable2D
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 // Resetable
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 // XMLIO
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