View Javadoc

1   // GeometricAlgebra Java package file
2   // Current version
3   // Go to ... http://sinai.mech.fukui-u.ac.jp/gcj/software/KamiWaAi/index.html
4   // Copyright (C) 2003, Eckhard M.S. Hitzer
5   //
6   // This library is free software; you can redistribute it and/or
7   // modify it under the terms of the GNU Lesser General Public
8   // License as published by the Free Software Foundation; either
9   // version 2.1 of the License, or any later version.
10  //
11  // This library is distributed in the hope that it will be useful,
12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  // Lesser General Public License for more details.
15  //
16  // You should have received a copy of the GNU Lesser General Public
17  // License along with this library; if not, write to the Free Software
18  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  // Go to ... http://www.gnu.org/copyleft/lesser.html
20  // 
21  // hitzer@mech.fukui-u.ac.jp
22  // 
23  // Department of Mechanical Engineering, Fukui University
24  // 3-9-1 Bunkyo, 910-8507 Fukui, Japan
25  // 
26  //
27  //
28  // It the personal wish of E.M.S. Hitzer,
29  // that you never use this software for infringing human dignity:
30  //
31  // "God created man in his own image,
32  // in the image of God he created him;
33  // male and female he created them.
34  // [The Bible, Genesis chapter 1 verse 27]
35  //
36  //
37  //
38  // 
39  //File Sphere.java
40  // 2003-5-1
41  // radius(), Center(), center() methods tested on 2003-1-29
42  package net.sourceforge.kamiwaai.geometricalgebra;
43  import java.awt.Color;
44  import java.awt.Graphics;
45  import java.util.Vector;
46  public class Sphere extends GeometricObject {
47  	private MultiVector[] basepoints = new MultiVector[4];
48  	// The default color of circles will be magenta.
49  	private Color color = Color.magenta;
50  	public Sphere(MultiVector L4) {
51  		L = L4;
52  	}
53  	public Sphere(PointC point1, PointC point2, PointC point3, PointC point4) {
54  		L = point1.getMultiVector().OutProd(point2.getMultiVector()).OutProd(
55  				point3.getMultiVector().OutProd(point4.getMultiVector()));
56  	}
57  	public Sphere(PointC centre, double radius){
58  		L = I.mult(centre.getMultiVector().sub(n.multSc(0.5*radius*radius))).multSc(2.0*radius*radius*radius);
59  	}
60  	public double radius() {
61  		double r2 = (L.ScProd(L)) * (1.0 / (n.OutProd(L).ScProd(n.OutProd(L))));
62  		double r = Math.sqrt(r2);
63  		return r;
64  	}
65  	public MultiVector Center() {
66  		// Gives the full conformal MultiVector for the center of the sphere
67  		MultiVector low = n.OutProd(L).mult(I).multSc(-1.0);
68  		double llow = low.ScProd(low);
69  		MultiVector Low = low.multSc(1.0 / llow); // inverse of low
70  		MultiVector Result = L.mult(I).mult(Low);
71  		double r = radius();
72  		MultiVector Cent = Result.add(n.multSc(0.5 * r * r));
73  		return Cent;
74  	}
75  	public double[] center() {
76  		// Gives the 3D Euclidean vector of the center of the circle
77  		double[] cvector = new double[3];
78  		Sphere LS = new Sphere(L);
79  		cvector[0] = LS.Center().get3DEuclidianPoint()[0];
80  		cvector[1] = LS.Center().get3DEuclidianPoint()[1];
81  		cvector[2] = LS.Center().get3DEuclidianPoint()[2];
82  		return cvector;
83  	}
84  	public MultiVector generator(int inc, MultiVector plane) {
85  		// Gives the Motor (MuliVector that rotates a given
86  		// angle increment 2pi/inc about the sphere's center)
87  		int UP = inc;
88  		double angle = 2 * Math.PI / UP; 
89  		MultiVector cv, Iplane, Tc, Tcr, R, D;
90  		cv = Center().OutProd(N).mult(N); // Euclidean 3D center vector.
91  		// Translation operator
92  		Tc = One.add(n.mult(cv).multSc(0.5));
93  		Tcr = Tc.reverse();
94  		Iplane = plane.multSc(1.0 / (plane.magnitude()));
95  		// Rotation rotor R:
96  		R = One.multSc(Math.cos(0.5 * angle)).add(
97  				Iplane.multSc(Math.sin(0.5 * angle)));
98  		// Operator for rotation about the circle center by angle increment.
99  		D = Tc.mult(R).mult(Tcr);
100 		return D;
101 	}
102 	public MultiVector PonS() {
103 		// Gives back one point on the sphere, which is e.g. used as the Pole
104 		// for generating a long. and lat. net of circles on the sphere,
105 		// and for picking the sphere itself.
106 		MultiVector rv, rad, Trad, Tradr, pons;
107 		double r;
108 		// Maybe later rv will be an input parameter for PonS
109 		rv = e1.add(e2).add(e3.multSc(-1.0));
110 		r = radius();
111 		rad = rv.multSc(r / (rv.magnitude()));
112 		// Translation operator from the center to a point on the cirlce itself
113 		Trad = One.add(n.mult(rad).multSc(0.5));
114 		Tradr = Trad.reverse();
115 		pons = Trad.mult(Center()).mult(Tradr);
116 		return pons;
117 	}
118 	public MultiVector PonSsouth() {
119 		// Gives back the point on the sphere opposite to the PonS() point Pole.
120 		// This makes the picking of a sphere more comfortable
121 		MultiVector rv, rad, Trad, Tradr, pons;
122 		double r;
123 		// Maybe later rv will be an input parameter for PonS
124 		rv = e1.add(e2).add(e3.multSc(-1.0));
125 		r = radius();
126 		rad = rv.multSc(r / (rv.magnitude()));
127 		// Translation operator from the center to a point on the cirlce itself
128 		Trad = One.add(n.mult(rad).multSc(0.5));
129 		Tradr = Trad.reverse();
130 		pons = Tradr.mult(Center()).mult(Trad);
131 		// The translation of the Center is opposite to the one in PonS()
132 		return pons;
133 	}
134 	public Vector snet(int inc) {
135 		// Gives back list of lat. and long. circles on the sphere
136 		Vector scnet = new Vector();
137 		MultiVector pole, center, A1, A2, A3, L3, D1, D1r, D2, D2r;
138 		MultiVector Iequp, Dlg, Dlgr;
139 		Circle C, C0;
140 		//Sphere LS = new Sphere(L);
141 		pole = PonS().OutProd(N).mult(N);
142 		center = Center().OutProd(N).mult(N);
143 		D1 = generator(2 * inc, pole.sub(center).OutProd(e1));
144 		D1r = D1.reverse();
145 		D2 = generator(2 * inc, pole.sub(center).OutProd(e2));
146 		D2r = D2.reverse();
147 		// Producing the latitudinal meridians:
148 		A1 = PonS();
149 		A2 = PonS();
150 		A3 = PonS();
151 		for (int k = 1; k < inc; k++) {
152 			A1 = D1.mult(A1).mult(D1r);
153 			A2 = D2.mult(A2).mult(D2r);
154 			A3 = D1r.mult(A3).mult(D1);
155 			L3 = A1.OutProd(A2).OutProd(A3);
156 			C = new Circle(L3);
157 			C.setColor(color);
158 			//if(k==1) Iequp = C.Cplane();
159 			scnet.add(C);
160 		}
161 		// This defines a 3D Euclidean bivector parallel to the
162 		// plane of the equator on the sphere relative to the Pole.
163 		Iequp = ((Circle) scnet.get(0)).Cplane();
164 		// Producing the longitudinal circles:
165 		A1 = PonS();
166 		A2 = D1.mult(A1).mult(D1r);
167 		A3 = D1r.mult(A1).mult(D1);
168 		L3 = A1.OutProd(A2).OutProd(A3);
169 		C0 = new Circle(L3);
170 		C0.setColor(color);
171 		scnet.add(C0);
172 		Dlg = generator(2 * inc, Iequp);
173 		Dlgr = Dlg.reverse();
174 		for (int k = 1; k < inc; k++) {
175 			C = new Circle((Dlg.Powerof(k)).mult(C0.getMultiVector()).mult(
176 					Dlgr.Powerof(k)));
177 			C.setColor(color);
178 			scnet.add(C);
179 		}
180 		return scnet;
181 		// Description of snet() method:
182 		// Define a set of inc horizontal (latitude) planes hplanes
183 		// Define a set of inc vertical (longitude) planes all containing rv
184 		// Which is longitudinal, which lateral? Name accordingly
185 		// Intersect these planes with the sphere LS to get the
186 		// net of circles (a vector of circles) which can be drawn with
187 		// the drawC() and drawCZ() methods of the circle objects.
188 		// Test every method with a simple example in GeoPro
189 	}
190 	public void setColor(Color c) {
191 		color = c;
192 	}
193 	public void draw(Graphics g) {
194 		Sphere LS = new Sphere(L);
195 		Vector SNET;
196 		SNET = LS.snet(6);
197 		for (int k = 0; k <= SNET.size() - 1; k++) {
198 			((Circle) SNET.get(k)).setColor(color);
199 			((Circle) SNET.get(k)).draw(g);
200 		}
201 	}
202 	public void drawZ(Graphics g) {
203 		Sphere LS = new Sphere(L);
204 		Vector SNET;
205 		SNET = LS.snet(6);
206 		for (int k = 0; k <= SNET.size() - 1; k++) {
207 			((Circle) SNET.get(k)).setColor(color);
208 			((Circle) SNET.get(k)).drawZ(g);
209 		}
210 	}
211 	public void setBasePoint(MultiVector basepoint, int p1to4) {
212 		basepoints[p1to4] = basepoint;
213 	}
214 	// This method is specific for remaking a sphere when one of its
215 	// basepoints is shifted!
216 	public void remake(MultiVector movedBP, int bpno) {
217 		basepoints[bpno] = movedBP;
218 		MultiVector Lnew = basepoints[0].OutProd(basepoints[1]).OutProd(
219 				basepoints[2].OutProd(basepoints[3]));
220 		L = Lnew;
221 	}
222 	public void recenter(MultiVector NewCenter) {
223 		MultiVector OldCenter, cDiff, Tc, Tcr, Lnew;
224 		Sphere LS = new Sphere(L);
225 		OldCenter = LS.Center();
226 		cDiff = NewCenter.get3DMVector().sub(OldCenter.get3DMVector());
227 		Tc = One.add(n.mult(cDiff).multSc(0.5));
228 		Tcr = Tc.reverse();
229 		Lnew = Tc.mult(L).mult(Tcr);
230 		L = Lnew;
231 	}
232 	private int MeetNo(Line line) {
233 		int meetno;
234 		double meet2 = meet(line).ScProd(meet(line));
235 		if (meet2 > 0.0)
236 			meetno = 2;
237 		else if (meet2 == 0.0)
238 			meetno = 1;
239 		else
240 			meetno = 0;
241 		return meetno;
242 	}
243 	public Vector MeetLineMVs(Line line) {
244 		Vector mline = new Vector();
245 		//Sphere S = new Sphere(L);
246 		int mno = MeetNo(line);
247 		//mline.add(mno); // This would add the number of intersection points
248 		MultiVector Meet, Meetp, u, v, a, b;
249 		double u2, gamma;
250 		//double[] a3D = new double[3];
251 		//double[] b3D = new double[3];
252 		Meet = meet(line);
253 		Meetp = Meet.sub(Meet.mult(N).getGrade(0).mult(N)); // Chopping off the
254 															// N part
255 		v = Meetp.mult(nbar).multSc(-1.0).getGrade(1).multSc(-2.0);
256 		u = Meetp.mult(n).multSc(-1.0).getGrade(1);
257 		u2 = u.ScProd(u);
258 		gamma = 2.0 * Meet.getnhnbPart().getScPart().RealPart();
259 		if (mno == 1) {
260 			MultiVector fact, factinv, A;
261 			fact = Meet.mult(n).multSc(-1.0).getGrade(1);
262 			factinv = fact.multSc(1.0 / (fact.magnitude() * fact.magnitude()));
263 			// This defines the full conformal vector aa:
264 			A = factinv.mult(Meet);
265 			// The spatial part of a seems to have the
266 			// right form for the mno = 2 case "stem" part
267 			//a3D[0] = -a.getnhnbPart().getBvPart()[0].ImaginaryPart();
268 			//a3D[1] = -a.getnhnbPart().getBvPart()[1].ImaginaryPart();
269 			//a3D[2] = -a.getnhnbPart().getBvPart()[2].ImaginaryPart();
270 			//mline.add(a3D);
271 			mline.add(A);
272 		} else {
273 			if (mno == 2 && gamma == 0.0) {
274 				MultiVector Bv, udB, x, stem, A, B;
275 				double ra = radius();
276 				Bv = Meetp.mult(N).getGrade(4).mult(N);
277 				udB = u.Lcontract(Bv);
278 				stem = udB.multSc(1.0 / u2);
279 				x = u.multSc(Math.sqrt(ra * ra / u2 - udB.ScProd(udB)
280 						/ (u2 * u2 * u2)));
281 				a = stem.add(x);
282 				b = stem.sub(x);
283 				A = a.add(n.multSc(0.5 * a.ScProd(a))).add(nbar);
284 				B = b.add(n.multSc(0.5 * b.ScProd(b))).add(nbar);
285 				//a3D[0] = -a.getnhnbPart().getBvPart()[0].ImaginaryPart();
286 				//a3D[1] = -a.getnhnbPart().getBvPart()[1].ImaginaryPart();
287 				//a3D[2] = -a.getnhnbPart().getBvPart()[2].ImaginaryPart();
288 				//b3D[0] = -b.getnhnbPart().getBvPart()[0].ImaginaryPart();
289 				//b3D[1] = -b.getnhnbPart().getBvPart()[1].ImaginaryPart();
290 				//b3D[2] = -b.getnhnbPart().getBvPart()[2].ImaginaryPart();
291 				mline.add(A);
292 				mline.add(B);
293 			} else if (mno == 2 && gamma != 0.0) {
294 				MultiVector A, B;
295 				double sigma, v2, rho, a2, b2;
296 				sigma = 0.5 * gamma * gamma - u.ScProd(v);
297 				v2 = v.ScProd(v);
298 				rho = Math.sqrt(sigma * sigma - v2 * u2);
299 				// In the following two lines, the sigma part produces
300 				// the "stem" part
301 				a2 = (sigma + rho) / u2;
302 				b2 = (sigma - rho) / u2;
303 				a = (u.multSc(a2).add(v)).multSc(1.0 / gamma);
304 				b = (u.multSc(b2).add(v)).multSc(1.0 / gamma);
305 				A = a.add(n.multSc(0.5 * a2)).add(nbar);
306 				B = b.add(n.multSc(0.5 * b2)).add(nbar);
307 				//a3D[0] = -a.getnhnbPart().getBvPart()[0].ImaginaryPart();
308 				//a3D[1] = -a.getnhnbPart().getBvPart()[1].ImaginaryPart();
309 				//a3D[2] = -a.getnhnbPart().getBvPart()[2].ImaginaryPart();
310 				//b3D[0] = -b.getnhnbPart().getBvPart()[0].ImaginaryPart();
311 				//b3D[1] = -b.getnhnbPart().getBvPart()[1].ImaginaryPart();
312 				//b3D[2] = -b.getnhnbPart().getBvPart()[2].ImaginaryPart();
313 				mline.add(A);
314 				mline.add(B);
315 			}
316 		}
317 		return mline;
318 	}
319 
320 }