public void TestFailingRealIntersections() { Scientrace.Object3dEnvironment env = DummySources.dEnv(); Scientrace.CylindricalBorder cb = new Scientrace.CylindricalBorder(new Scientrace.Location(0, -0.07, 0), new Scientrace.NonzeroVector(0, -0.57, 0), 0.5); Scientrace.ParabolicMirror pm = new Scientrace.ParabolicMirror(env , Scientrace.PerfectMirror.Instance, new Scientrace.Location(0.354861881099294, -0.57, 0.276718350209505) , new Scientrace.UnitVector(-0.343710964996787, 0.900014703397015, -0.268022958363946), 2, cb); Scientrace.Line tl = new Scientrace.Line(-0.184140645666577, -0.0383229578843359, -0.3, 0.343710966184079, -0.900014705907235, 0.268022948412108); // pm.trf.transform(tl); // Scientrace.IntersectionPoint[] tips = pm.realIntersections(tl); //Assert.AreEqual(new Scientrace.Location(0,0,0), tips[0].loc); Scientrace.VectorTransform trf = pm.trf; Scientrace.Line trfline = trf.transform(tl - pm.loc); //transform location AND direction Scientrace.IntersectionPoint[] ips = pm.baseintersections(trfline); //Scientrace.IntersectionPoint tip; Scientrace.IntersectionPoint[] retips = new Scientrace.IntersectionPoint[2]; for (int ipi = 0; ipi < ips.GetLength(0); ipi++) { if (ips[ipi] == null) { retips[ipi] = null; continue; } //check below removed for performance reasons if (!trfline.throughLocation(ips[ipi].loc, 0.00001)) { string warning = @"ERROR: GOING DOWN! \n baseintersections " + trfline + " FAILED!"; throw new ArgumentOutOfRangeException(warning + ips[ipi].loc.trico() + " not in line " + trfline); } } }
public void TestFailingRealIntersections() { Scientrace.Object3dEnvironment env = DummySources.dEnv(); Scientrace.CylindricalBorder cb = new Scientrace.CylindricalBorder(new Scientrace.Location(0, -0.07, 0), new Scientrace.NonzeroVector(0, -0.57, 0), 0.5); Scientrace.ParabolicMirror pm = new Scientrace.ParabolicMirror(env , Scientrace.PerfectMirror.Instance, new Scientrace.Location(0.354861881099294, -0.57, 0.276718350209505) , new Scientrace.UnitVector(-0.343710964996787, 0.900014703397015, -0.268022958363946), 2, cb); Scientrace.Line tl = new Scientrace.Line(-0.184140645666577, -0.0383229578843359, -0.3, 0.343710966184079, -0.900014705907235, 0.268022948412108); // pm.trf.transform(tl); // Scientrace.IntersectionPoint[] tips = pm.realIntersections(tl); //Assert.AreEqual(new Scientrace.Location(0,0,0), tips[0].loc); Scientrace.VectorTransform trf = pm.trf; Scientrace.Line trfline = trf.transform(tl-pm.loc); //transform location AND direction Scientrace.IntersectionPoint[] ips = pm.baseintersections(trfline); //Scientrace.IntersectionPoint tip; Scientrace.IntersectionPoint[] retips = new Scientrace.IntersectionPoint[2]; for (int ipi = 0; ipi < ips.GetLength(0); ipi++) { if (ips[ipi] == null) { retips[ipi] = null; continue; } //check below removed for performance reasons if (!trfline.throughLocation(ips[ipi].loc, 0.00001)) { string warning =@"ERROR: GOING DOWN! \n baseintersections "+trfline+" FAILED!"; throw new ArgumentOutOfRangeException(warning+ips[ipi].loc.trico() + " not in line " + trfline); } } }
//copy constructor public Intersection(Intersection copyIntersection) { this.intersects = copyIntersection.intersects; this.object3d = copyIntersection.object3d; this.leaving = copyIntersection.leaving; if (copyIntersection.enter != null) this.enter = new Scientrace.IntersectionPoint(copyIntersection.enter); if (copyIntersection.exit != null) this.exit = new Scientrace.IntersectionPoint(copyIntersection.exit); }
public Scientrace.IntersectionPoint filterOutsideBorder(Scientrace.IntersectionPoint anIP) { if (anIP == null) { return(null); } return (this.contains(anIP.loc) ? anIP : null); }
//copy constructor public Intersection(Intersection copyIntersection) { this.intersects = copyIntersection.intersects; this.object3d = copyIntersection.object3d; this.leaving = copyIntersection.leaving; if (copyIntersection.enter != null) { this.enter = new Scientrace.IntersectionPoint(copyIntersection.enter); } if (copyIntersection.exit != null) { this.exit = new Scientrace.IntersectionPoint(copyIntersection.exit); } }
public IntersectionPoint[] intersects11circleborder(Trace trace) { Scientrace.Line line = trace.traceline; double d1, d2, dx, dy, lx, ly; double ABCa, ABCb, ABCc, discr; Scientrace.Vector v1, v2; Scientrace.FlatShape2d plane1, plane2; Scientrace.IntersectionPoint[] ip; dx = line.direction.x; dy = line.direction.y; lx = line.startingpoint.x; ly = line.startingpoint.y; ABCa = Math.Pow(ly, 2) + Math.Pow(lx, 2); ABCb = 2 * ((ly * dy) + (lx * dx)); ABCc = Math.Pow(dy, 2) + Math.Pow(dx, 2) - 1; discr = Math.Pow(ABCb, 2) - (4 * ABCa * ABCc); if (discr < 0) { ip = new Scientrace.IntersectionPoint[0]; //ip[0] = null; //ip[1] = null; return(ip); } if (discr == 0) { ip = new Scientrace.IntersectionPoint[1]; d1 = ((-ABCb) + Math.Sqrt(Math.Pow(ABCb, 2) - (4 * ABCa * ABCc))) / (2 * ABCa); v1 = (line.direction.toVector() * d1) + line.startingpoint.toVector(); //plane1 is based on v1 rotated 90 degrees which makes: x' = -y, y' = x, z = z plane1 = new Scientrace.FlatShape2d(v1.toLocation(), new Scientrace.UnitVector(0, 0, 1), new Scientrace.UnitVector(-v1.y, v1.x, v1.z)); ip[0] = new IntersectionPoint(v1.toLocation(), plane1); return(ip); } d1 = ((-ABCb) + Math.Sqrt(Math.Pow(ABCb, 2) - (4 * ABCa * ABCc))) / (2 * ABCa); d2 = ((-ABCb) - Math.Sqrt(Math.Pow(ABCb, 2) - (4 * ABCa * ABCc))) / (2 * ABCa); v1 = (line.direction.toVector() * d1) + line.startingpoint.toVector(); v2 = (line.direction.toVector() * d2) + line.startingpoint.toVector(); ip = new Scientrace.IntersectionPoint[2]; plane1 = new Scientrace.FlatShape2d(v1.toLocation(), new Scientrace.UnitVector(0, 0, 1), new Scientrace.UnitVector(-v1.y, v1.x, v1.z)); ip[0] = new IntersectionPoint(v1.toLocation(), plane1); plane2 = new Scientrace.FlatShape2d(v2.toLocation(), new Scientrace.UnitVector(0, 0, 1), new Scientrace.UnitVector(-v2.y, v2.x, v2.z)); ip[1] = new IntersectionPoint(v2.toLocation(), plane2); return(ip); }
public Intersection(bool intersects, Scientrace.Object3d object3d, Scientrace.Location enterloc, Scientrace.FlatShape2d enterplane, Scientrace.Location exitloc, bool leaving) { this.intersects = intersects; this.object3d = object3d; this.enter = new IntersectionPoint(enterloc, enterplane); //plane of exitloc irrelevant if (exitloc == null) { this.exit = null; } else { this.exit = new IntersectionPoint(exitloc, null); } this.leaving = leaving; this.checkObject();//<- DEBUGGING: }
public Intersection(bool intersects, Scientrace.Object3d object3d, Scientrace.Location enterloc, Scientrace.FlatShape2d enterplane, Scientrace.Location exitloc) { //same as constructor above but with leaving = false. this.intersects = intersects; this.object3d = object3d; this.enter = new IntersectionPoint(enterloc, enterplane); if (exitloc == null) { this.exit = null; } else { this.exit = new IntersectionPoint(exitloc, null); } this.leaving = false; this.checkObject();//<- DEBUGGING: }
public void TestIntersectionByVectorArray3() { Scientrace.Object3dEnvironment env = new Scientrace.Object3dEnvironment(Scientrace.AirProperties.Instance, 100); Scientrace.Line beam = new Scientrace.Line(10, 10, 10, -1, -1, 0); Scientrace.LightSource light = new Scientrace.SingleRaySource(beam, 10, new Scientrace.AM15Spectrum(1), env); Scientrace.Trace trace = new Scientrace.Trace(500.0E-9, light, beam, env, 1, 1); Console.WriteLine(trace.ToString()); //Scientrace.Vector v = new Scientrace.Vector(10,10,10); Scientrace.IntersectionPoint[] ips = new Scientrace.IntersectionPoint[2]; ips[0] = null; ips[1] = null; //Scientrace.Intersection intr = new Scientrace.Intersection(trace, ips); //Assert.IsFalse(intr.intersects); }
public void TestIntersectionByVectorArray3() { Scientrace.Object3dEnvironment env = new Scientrace.Object3dEnvironment(Scientrace.AirProperties.Instance, 100); Scientrace.Line beam = new Scientrace.Line(10, 10, 10, -1, -1, 0); Scientrace.LightSource light = new Scientrace.SingleRaySource(beam, 10, new Scientrace.AM15Spectrum(1), env); Scientrace.Trace trace = new Scientrace.Trace(500.0E-9, light, beam, env,1,1); Console.WriteLine(trace.ToString()); //Scientrace.Vector v = new Scientrace.Vector(10,10,10); Scientrace.IntersectionPoint[] ips = new Scientrace.IntersectionPoint[2]; ips[0] = null; ips[1] = null; //Scientrace.Intersection intr = new Scientrace.Intersection(trace, ips); //Assert.IsFalse(intr.intersects); }
public Intersection(bool intersects, Scientrace.Object3d object3d, Scientrace.Location enterloc, Scientrace.FlatShape2d enterplane, Scientrace.Location exitloc, bool leaving) { this.intersects = intersects; this.object3d = object3d; this.enter = new IntersectionPoint(enterloc, enterplane); //plane of exitloc irrelevant if (exitloc == null) { this.exit = null; } else { this.exit = new IntersectionPoint(exitloc, null); } this.leaving = leaving; this.checkObject(); //<- DEBUGGING: }
public Intersection(bool intersects, Scientrace.Object3d object3d, Scientrace.Location enterloc, Scientrace.FlatShape2d enterplane, Scientrace.Location exitloc) { //same as constructor above but with leaving = false. this.intersects = intersects; this.object3d = object3d; this.enter = new IntersectionPoint(enterloc, enterplane); if (exitloc == null) { this.exit = null; } else { this.exit = new IntersectionPoint(exitloc, null); } this.leaving = false; this.checkObject(); //<- DEBUGGING: }
public override Intersection intersects(Scientrace.Trace aTrace) { Scientrace.Vector c = this.loc; Scientrace.Vector o = aTrace.traceline.startingpoint; Scientrace.Vector l = aTrace.traceline.direction; Scientrace.Vector y = o - c; double r = this.radius; double ABCa = l.dotProduct(l); double ABCb = l.dotProduct(y) * 2; double ABCc = y.dotProduct(y) - (r * r); QuadraticEquation qe = new QuadraticEquation(ABCa, ABCb, ABCc); // if the trace doesn't hit the sphere, return a "false Intersection" if (!qe.hasAnswers) { return(new Intersection(false, this)); } Scientrace.IntersectionPoint[] ips = new Scientrace.IntersectionPoint[2]; switch (qe.answerCount) { case 2: Scientrace.Location minLoc = ((l * qe.minVal) + o).toLocation(); Scientrace.NonzeroVector minNorm = (minLoc - c).tryToNonzeroVector(); ips[0] = Scientrace.IntersectionPoint.locAtSurfaceNormal(minLoc, minNorm); Scientrace.Location plusLoc = ((l * qe.plusVal) + o).toLocation(); Scientrace.NonzeroVector plusNorm = (plusLoc - c).tryToNonzeroVector(); ips[1] = Scientrace.IntersectionPoint.locAtSurfaceNormal(plusLoc, plusNorm); return(new Intersection(aTrace, ips, this)); //goto case 1; //continue to case 1 case 1: Scientrace.Location loc = ((l * qe.plusVal) + o).toLocation(); Scientrace.NonzeroVector norm = (loc - c).tryToNonzeroVector(); ips[0] = Scientrace.IntersectionPoint.locAtSurfaceNormal(loc, norm); ips[1] = null; return(new Intersection(aTrace, ips, this)); default: throw new IndexOutOfRangeException("eq.answerCount is not allowed to be " + qe.answerCount.ToString() + "in Shpere.intersects(..)"); } //end switch(qe.answerCount) }
public override Intersection intersects(Scientrace.Trace aTrace) { // Finding intersectionpoints at sphere Scientrace.Intersection sphereIntersections = this.dummySphere.intersects(aTrace); /* If the PlanoConvexLens doesn't even pass the surface of the sphere, the intersection * of the lens does not exist. */ if (!sphereIntersections.intersects) { //return sphereIntersections; return(Intersection.notIntersect(this)); } Scientrace.Location planoLoc = this.lensPlane.lineThroughPlane(aTrace.traceline); Scientrace.IntersectionPoint planoIP; if ((!this.dummySphere.contains(planoLoc)) || (planoLoc == null)) { planoIP = null; } else { planoIP = new Scientrace.IntersectionPoint(planoLoc, this.lensPlane.planeToFlatShape2d()); } Scientrace.IntersectionPoint[] ips = new Scientrace.IntersectionPoint[3]; ips[0] = planoIP; ips[1] = this.lensPlane.filterOutsideBorder(sphereIntersections.enter); ips[2] = this.lensPlane.filterOutsideBorder(sphereIntersections.exit); Scientrace.Intersection lensIntersection = new Scientrace.Intersection(aTrace, ips, this); // when currently inside the lens, intersection from here must mean leaving. lensIntersection.leaving = this.contains(aTrace.traceline.startingpoint); //return created new intersection return(lensIntersection); }
public override Intersection intersects(Scientrace.Trace aTrace) { // Finding intersectionpoints at sphere Scientrace.Intersection sphereIntersections = this.dummySphere.intersects(aTrace); /* If the PlanoConvexLens doesn't even pass the surface of the sphere, the intersection of the lens does not exist. */ if (!sphereIntersections.intersects) { //return sphereIntersections; return Intersection.notIntersect(this); } Scientrace.Location planoLoc = this.lensPlane.lineThroughPlane(aTrace.traceline); Scientrace.IntersectionPoint planoIP; if ((!this.dummySphere.contains(planoLoc)) || (planoLoc == null)) { planoIP = null; } else { planoIP = new Scientrace.IntersectionPoint(planoLoc, this.lensPlane.planeToFlatShape2d()); } Scientrace.IntersectionPoint[] ips = new Scientrace.IntersectionPoint[3]; ips[0] = planoIP; ips[1] = this.lensPlane.filterOutsideBorder(sphereIntersections.enter); ips[2] = this.lensPlane.filterOutsideBorder(sphereIntersections.exit); Scientrace.Intersection lensIntersection = new Scientrace.Intersection(aTrace, ips, this); // when currently inside the lens, intersection from here must mean leaving. lensIntersection.leaving = this.contains(aTrace.traceline.startingpoint); //return created new intersection return lensIntersection; }
public void removeExit() { this.exit = new IntersectionPoint(null, null); this.leaving = true; }
public override Intersection intersects(Scientrace.Trace aTrace) { Scientrace.Vector c = this.loc; Scientrace.Vector o = aTrace.traceline.startingpoint; Scientrace.Vector l = aTrace.traceline.direction; Scientrace.Vector y = o-c; double r = this.radius; double ABCa = l.dotProduct(l); double ABCb = l.dotProduct(y)*2; double ABCc = y.dotProduct(y)-(r*r); QuadraticEquation qe = new QuadraticEquation(ABCa,ABCb,ABCc); // if the trace doesn't hit the sphere, return a "false Intersection" if (!qe.hasAnswers) { return new Intersection(false, this); } Scientrace.IntersectionPoint[] ips = new Scientrace.IntersectionPoint[2]; switch (qe.answerCount) { case 2: Scientrace.Location minLoc = ((l*qe.minVal) + o).toLocation(); Scientrace.NonzeroVector minNorm = (minLoc - c).tryToNonzeroVector(); ips[0] = Scientrace.IntersectionPoint.locAtSurfaceNormal(minLoc, minNorm); Scientrace.Location plusLoc = ((l*qe.plusVal) + o).toLocation(); Scientrace.NonzeroVector plusNorm = (plusLoc - c).tryToNonzeroVector(); ips[1] = Scientrace.IntersectionPoint.locAtSurfaceNormal(plusLoc, plusNorm); return new Intersection(aTrace, ips, this); //goto case 1; //continue to case 1 case 1: Scientrace.Location loc = ((l*qe.plusVal) + o).toLocation(); Scientrace.NonzeroVector norm = (loc - c).tryToNonzeroVector(); ips[0] = Scientrace.IntersectionPoint.locAtSurfaceNormal(loc, norm); ips[1] = null; return new Intersection(aTrace, ips, this); default: throw new IndexOutOfRangeException("eq.answerCount is not allowed to be "+qe.answerCount.ToString()+"in Shpere.intersects(..)"); } //end switch(qe.answerCount) }
public void initNewIntersection(Scientrace.Line traceline, Scientrace.IntersectionPoint[] ips, Scientrace.Object3d object3d, bool bothdirections) { this.object3d = object3d; //Console.WriteLine("New Intersection with "+ips.Length+" IP's - "+object3d.hasParent()); this.intersects = false; //Console.WriteLine("FALSE"); foreach (Scientrace.IntersectionPoint ip in ips) { if (ip == null) { //Console.WriteLine("<NULL>"); continue; } //if bothdirections == true the Intersection does not nessicarily have to be away (in direction "direction") // from the startingpoint. if (!bothdirections) { //check if ip is in the line of the trace from its startingpoint if (traceline.direction.dotProduct(ip.loc - traceline.startingpoint) <= 1E-9) { //Console.WriteLine("WARNING: Intersectionpoint "+ip.loc.ToString()+" lies in the past @ "+traceline.startingpoint); continue; } } if (this.intersects == false) { //Console.WriteLine("TRUE"); this.intersects = true; this.enter = ip; this.exit = null; // new IntersectionPoint(null, null); CHANGED (BUGFIX?) BY JBC @ 20131205 continue; } if (this.enter.loc.distanceTo(traceline.startingpoint) > ip.loc.distanceTo(traceline.startingpoint)) { //this intersectionpoint is closer than the "enterpoint so far" // this condition is wrong right? if (this.exit==null) { this.exit = this.enter; // this is wrong right? } this.enter = ip; continue; } else { if (this.exit == null) { this.exit = ip; continue; } else { //this intersectionpoint is further from beam than enterpoint. New exitpoint defined. if (this.exit.loc.distanceTo(traceline.startingpoint) > ip.loc.distanceTo(traceline.startingpoint)) { //intersectionpoint is closer than old exitpoint this.exit = ip; continue; } } continue; // <-- existing exitpoint is closer than new IP: do nothing. } } }
public IntersectionPoint[] intersects11circleborder(Trace trace) { Scientrace.Line line = trace.traceline; double d1, d2, dx, dy, lx, ly; double ABCa, ABCb, ABCc, discr; Scientrace.Vector v1, v2; Scientrace.FlatShape2d plane1, plane2; Scientrace.IntersectionPoint[] ip; dx = line.direction.x; dy = line.direction.y; lx = line.startingpoint.x; ly = line.startingpoint.y; ABCa = Math.Pow(ly,2)+Math.Pow(lx,2); ABCb = 2*((ly*dy) + (lx*dx)); ABCc = Math.Pow(dy,2)+Math.Pow(dx,2)-1; discr = Math.Pow(ABCb, 2)-(4*ABCa*ABCc); if (discr < 0) { ip = new Scientrace.IntersectionPoint[0]; //ip[0] = null; //ip[1] = null; return ip; } if (discr == 0) { ip = new Scientrace.IntersectionPoint[1]; d1 = ((-ABCb)+Math.Sqrt(Math.Pow(ABCb, 2)-(4*ABCa*ABCc)))/(2*ABCa); v1 = (line.direction.toVector()*d1)+line.startingpoint.toVector(); //plane1 is based on v1 rotated 90 degrees which makes: x' = -y, y' = x, z = z plane1 = new Scientrace.FlatShape2d(v1.toLocation(), new Scientrace.UnitVector(0,0,1), new Scientrace.UnitVector(-v1.y, v1.x, v1.z)); ip[0] = new IntersectionPoint(v1.toLocation(), plane1); return ip; } d1 = ((-ABCb)+Math.Sqrt(Math.Pow(ABCb, 2)-(4*ABCa*ABCc)))/(2*ABCa); d2 = ((-ABCb)-Math.Sqrt(Math.Pow(ABCb, 2)-(4*ABCa*ABCc)))/(2*ABCa); v1 = (line.direction.toVector()*d1)+line.startingpoint.toVector(); v2 = (line.direction.toVector()*d2)+line.startingpoint.toVector(); ip = new Scientrace.IntersectionPoint[2]; plane1 = new Scientrace.FlatShape2d(v1.toLocation(), new Scientrace.UnitVector(0,0,1), new Scientrace.UnitVector(-v1.y, v1.x, v1.z)); ip[0] = new IntersectionPoint(v1.toLocation(), plane1); plane2 = new Scientrace.FlatShape2d(v2.toLocation(), new Scientrace.UnitVector(0,0,1), new Scientrace.UnitVector(-v2.y, v2.x, v2.z)); ip[1] = new IntersectionPoint(v2.toLocation(), plane2); return ip; }
/* end of interface IBorder3D implementation */ public IntersectionPoint[] intersectionPoints(Trace trace) { VectorTransform trf = this.getTransform(); // the points (any V) on the center line of this cylinder is described by "V = s + x l" for any x. Vector s = trf.transform(trace.traceline.startingpoint - this.loc); Vector l = trf.transform(trace.traceline.direction); double r = 1; // not (this.radius;) as the transformation rendered it 1. double ABCa = Math.Pow(l.x, 2) + Math.Pow(l.y, 2); double ABCb = 2 * ((s.x * l.x) + (s.y * l.y)); double ABCc = Math.Pow(s.x, 2) + Math.Pow(s.y, 2) - r * r; QuadraticEquation qe = new QuadraticEquation(ABCa, ABCb, ABCc); Scientrace.IntersectionPoint[] ips = new Scientrace.IntersectionPoint[2] { null, null }; if (!qe.hasAnswers) { return(ips); } for (int iAns = 1; iAns <= qe.answerCount; iAns++) { double x = qe.getAnswer(iAns); if (Double.IsNaN(x)) { throw new ArgumentNullException("Answer {" + iAns + "} is NaN.\n\n qe details:" + qe.ToString()); } Vector tLoc = s + (l * x); Vector tNormal = new Vector(tLoc.x, tLoc.y, 0); Location oLoc = (trf.transformback(tLoc) + this.loc).toLocation(); UnitVector oNormal = null; try { oNormal = trf.transformback(tNormal).tryToUnitVector(); } catch { new ZeroNonzeroVectorException("oNormal is a zerovector which cannot be normalised for o3d [" + this.tag + "] and trace " + trace.ToCompactString()); } ips[iAns - 1] = Scientrace.IntersectionPoint.locAtSurfaceNormal(oLoc, oNormal); } /* switch (qe.answerCount) { * case 2: * Scientrace.Location minLoc = ((l*qe.minVal) + o).toLocation(); * Scientrace.NonzeroVector minNorm = (minLoc - c).tryToNonzeroVector(); * ips[0] = Scientrace.IntersectionPoint.locAtSurfaceNormal(minLoc, minNorm); * Scientrace.Location plusLoc = ((l*qe.plusVal) + o).toLocation(); * Scientrace.NonzeroVector plusNorm = (plusLoc - c).tryToNonzeroVector(); * ips[1] = Scientrace.IntersectionPoint.locAtSurfaceNormal(plusLoc, plusNorm); * return new Intersection(aTrace, ips, this); * //goto case 1; //continue to case 1 * case 1: * Scientrace.Location loc = ((l*qe.plusVal) + o).toLocation(); * Scientrace.NonzeroVector norm = (loc - c).tryToNonzeroVector(); * ips[0] = Scientrace.IntersectionPoint.locAtSurfaceNormal(loc, norm); * ips[1] = null; * return new Intersection(aTrace, ips, this); * default: * throw new IndexOutOfRangeException("eq.answerCount is not allowed to be "+qe.answerCount.ToString()+"in Shpere.intersects(..)"); * } //end switch(qe.answerCount) */ return(ips); }
/* end of interface IBorder3D implementation */ public IntersectionPoint[] intersectionPoints(Trace trace) { VectorTransform trf = this.getTransform(); // the points (any V) on the center line of this cylinder is described by "V = s + x l" for any x. Vector s = trf.transform(trace.traceline.startingpoint-this.loc); Vector l = trf.transform(trace.traceline.direction); double r = 1; // not (this.radius;) as the transformation rendered it 1. double ABCa = Math.Pow(l.x,2) + Math.Pow(l.y,2); double ABCb = 2*((s.x*l.x)+(s.y*l.y)); double ABCc = Math.Pow(s.x,2) + Math.Pow(s.y,2) - r*r; QuadraticEquation qe = new QuadraticEquation(ABCa, ABCb, ABCc); Scientrace.IntersectionPoint[] ips = new Scientrace.IntersectionPoint[2]{null, null}; if (!qe.hasAnswers) { return ips; } for (int iAns = 1; iAns <= qe.answerCount; iAns++) { double x = qe.getAnswer(iAns); if (Double.IsNaN(x)) throw new ArgumentNullException("Answer {"+iAns+"} is NaN.\n\n qe details:"+qe.ToString()); Vector tLoc = s + (l * x); Vector tNormal = new Vector(tLoc.x, tLoc.y, 0); Location oLoc = (trf.transformback(tLoc)+this.loc).toLocation(); UnitVector oNormal = null; try { oNormal = trf.transformback(tNormal).tryToUnitVector(); } catch { new ZeroNonzeroVectorException("oNormal is a zerovector which cannot be normalised for o3d ["+this.tag+"] and trace "+trace.ToCompactString()); } ips[iAns-1] = Scientrace.IntersectionPoint.locAtSurfaceNormal(oLoc, oNormal); } /* switch (qe.answerCount) { case 2: Scientrace.Location minLoc = ((l*qe.minVal) + o).toLocation(); Scientrace.NonzeroVector minNorm = (minLoc - c).tryToNonzeroVector(); ips[0] = Scientrace.IntersectionPoint.locAtSurfaceNormal(minLoc, minNorm); Scientrace.Location plusLoc = ((l*qe.plusVal) + o).toLocation(); Scientrace.NonzeroVector plusNorm = (plusLoc - c).tryToNonzeroVector(); ips[1] = Scientrace.IntersectionPoint.locAtSurfaceNormal(plusLoc, plusNorm); return new Intersection(aTrace, ips, this); //goto case 1; //continue to case 1 case 1: Scientrace.Location loc = ((l*qe.plusVal) + o).toLocation(); Scientrace.NonzeroVector norm = (loc - c).tryToNonzeroVector(); ips[0] = Scientrace.IntersectionPoint.locAtSurfaceNormal(loc, norm); ips[1] = null; return new Intersection(aTrace, ips, this); default: throw new IndexOutOfRangeException("eq.answerCount is not allowed to be "+qe.answerCount.ToString()+"in Shpere.intersects(..)"); } //end switch(qe.answerCount) */ return ips; }
public override Intersection intersects(Trace aTrace) { /* OK, this is how we are going to do this: * First (1), we find all intersectionpoints for all sub-borders and order them * as a function of the distance from the startingpoint of the trace. Then (2), we * take the average location in between two consecutive intersectionpoints. Let's * ask all SubVolumes if anybody has this average value in it's body (3). We will * repeat this procedure until we find an average value that is *NOT* included (4). The * very first intersectionpoint, and the last intersectionpoint before that latest * assessed average will be the two intersectionpoints construction the Intersection (5) * value to return. * A final remark must be made: when a trace is leaving from the current object and the * average location between the start of the trace and the first intersection is also * within the object, the first intersectionpoint is actually virtual and should be * removed. (6) */ // (1) // create an orderedlist with as keys the distances from the last intersection to this ip SortedList<double,IntersectionPoint> all_ips = new SortedList<double,IntersectionPoint>(); Scientrace.Location subTraceStart = aTrace.traceline.startingpoint; foreach (PlaneBorderEnclosedVolume aSubVolume in subVolumes) { Intersection tIntersection = aSubVolume.intersects(aTrace); if (tIntersection.intersects) { this.conditionalIPList(all_ips, tIntersection, subTraceStart); } } IntersectionPoint previous_ip = null; IntersectionPoint first_ip = null; IntersectionPoint last_ip = null; for (int iKey = 0; iKey < all_ips.Keys.Count; iKey++) { double currentKey = all_ips.Keys[iKey]; IntersectionPoint currentIP = all_ips[currentKey]; if (previous_ip == null) { // is this the last IP in the list? if (iKey != all_ips.Count-1) { // If both the area between the start of the trace and that between this and the next trace is contained, skip to the next (by continue) IntersectionPoint nextIP = all_ips[all_ips.Keys[iKey+1]]; if (this.contains(subTraceStart.avgWith(currentIP.loc)) && this.contains(currentIP.loc.avgWith(nextIP.loc))) { continue; } } // (6) if (this.contains(subTraceStart.avgWith(currentIP.loc)) && (iKey+1!=all_ips.Keys.Count)) { first_ip = currentIP; break; } else { // the first ip in the list, no average to take with previous value first_ip = currentIP; } } else { // (2) Scientrace.Location average_loc = currentIP.loc.avgWith(previous_ip.loc); // (3) if (!this.contains(average_loc)) { //Console.WriteLine("BREAKOUT!!!!"); last_ip = previous_ip; // (4) Break out of foreach loop, we've found the last point in this intersection (the previous one in the list) break; } } // last statement in foreach loop, defining the current IP als the previous for the next cycle. previous_ip = currentIP; } // there has to be at least ONE intersection to succeed... if (first_ip == null) { return Intersection.notIntersect(this); } /* below must be the most obscure line in this routine, sry about that. * it does this: if last_ip is still unassigned, assign previous_ip as long as it differs from first_ip... */ // last_ip = last_ip ?? (previous_ip != first_ip ? previous_ip : null); if (last_ip == null) last_ip = (previous_ip != first_ip ? previous_ip : null); // (5) Scientrace.IntersectionPoint[] real_ips = new Scientrace.IntersectionPoint[2]; real_ips[0] = first_ip; real_ips[1] = last_ip; Intersection retIntersect = new Intersection(aTrace, real_ips, this); return retIntersect; //end func. intersect }
public override Intersection intersects(Trace aTrace) { /* OK, this is how we are going to do this: * First (1), we find all intersectionpoints for all sub-borders and order them * as a function of the distance from the startingpoint of the trace. Then (2), we * take the average location in between two consecutive intersectionpoints. Let's * ask all SubVolumes if anybody has this average value in it's body (3). We will * repeat this procedure until we find an average value that is *NOT* included (4). The * very first intersectionpoint, and the last intersectionpoint before that latest * assessed average will be the two intersectionpoints construction the Intersection (5) * value to return. * A final remark must be made: when a trace is leaving from the current object and the * average location between the start of the trace and the first intersection is also * within the object, the first intersectionpoint is actually virtual and should be * removed. (6) */ // (1) // create an orderedlist with as keys the distances from the last intersection to this ip SortedList <double, IntersectionPoint> all_ips = new SortedList <double, IntersectionPoint>(); Scientrace.Location subTraceStart = aTrace.traceline.startingpoint; foreach (PlaneBorderEnclosedVolume aSubVolume in subVolumes) { Intersection tIntersection = aSubVolume.intersects(aTrace); if (tIntersection.intersects) { this.conditionalIPList(all_ips, tIntersection, subTraceStart); } } IntersectionPoint previous_ip = null; IntersectionPoint first_ip = null; IntersectionPoint last_ip = null; for (int iKey = 0; iKey < all_ips.Keys.Count; iKey++) { double currentKey = all_ips.Keys[iKey]; IntersectionPoint currentIP = all_ips[currentKey]; if (previous_ip == null) { // is this the last IP in the list? if (iKey != all_ips.Count - 1) { // If both the area between the start of the trace and that between this and the next trace is contained, skip to the next (by continue) IntersectionPoint nextIP = all_ips[all_ips.Keys[iKey + 1]]; if (this.contains(subTraceStart.avgWith(currentIP.loc)) && this.contains(currentIP.loc.avgWith(nextIP.loc))) { continue; } } // (6) if (this.contains(subTraceStart.avgWith(currentIP.loc)) && (iKey + 1 != all_ips.Keys.Count)) { first_ip = currentIP; break; } else { // the first ip in the list, no average to take with previous value first_ip = currentIP; } } else { // (2) Scientrace.Location average_loc = currentIP.loc.avgWith(previous_ip.loc); // (3) if (!this.contains(average_loc)) { //Console.WriteLine("BREAKOUT!!!!"); last_ip = previous_ip; // (4) Break out of foreach loop, we've found the last point in this intersection (the previous one in the list) break; } } // last statement in foreach loop, defining the current IP als the previous for the next cycle. previous_ip = currentIP; } // there has to be at least ONE intersection to succeed... if (first_ip == null) { return(Intersection.notIntersect(this)); } /* below must be the most obscure line in this routine, sry about that. * it does this: if last_ip is still unassigned, assign previous_ip as long as it differs from first_ip... */ // last_ip = last_ip ?? (previous_ip != first_ip ? previous_ip : null); if (last_ip == null) { last_ip = (previous_ip != first_ip ? previous_ip : null); } // (5) Scientrace.IntersectionPoint[] real_ips = new Scientrace.IntersectionPoint[2]; real_ips[0] = first_ip; real_ips[1] = last_ip; Intersection retIntersect = new Intersection(aTrace, real_ips, this); return(retIntersect); //end func. intersect }
public void removeExit() { this.exit = new IntersectionPoint(null,null); this.leaving = true; }
public Scientrace.IntersectionPoint[] realIntersections(Scientrace.Line traceline, bool checkBorder) { // Scientrace.Line line = traceline-this.loc; //substract loc value from traceline location, //leave direction unchanged //Console.WriteLine("In untransformed world: traceline -> "+traceline.ToString()); //default value should be checkBorder = true; Scientrace.VectorTransform trf = this.trf; Scientrace.Line trfline = trf.transform(traceline - this.loc); //transform location AND direction Scientrace.IntersectionPoint[] ips = this.baseintersections(trfline); Scientrace.IntersectionPoint tip; Scientrace.IntersectionPoint[] retips = new Scientrace.IntersectionPoint[2]; for (int ipi = 0; ipi < ips.GetLength(0); ipi++) { if (ips[ipi] == null) { retips[ipi] = null; continue; } //Console.WriteLine("$$$$$$$$$$$$$$$$$"+ips[ipi].loc+"in?:"+trfline); //Console.WriteLine("___1"); //check below removed for performance reasons /*if (!trfline.throughLocation(ips[ipi].loc, 0.00001)) { * string warning =@"ERROR: GOING DOWN! \n baseintersections "+trfline+" FAILED!"; * throw new ArgumentOutOfRangeException(warning+ips[ipi].loc.trico() + " not in line " + trfline); * } *///This was removed at 20160222 /* else { * Scientrace.Line reflline = trfline.reflectAt(this.baseIntersectionPlane(ips[ipi].loc.x, ips[ipi].loc.y),0); * //Console.WriteLine("___2"); * /*if (!reflline.throughLocation(this.getBaseConcentrationPoint(), 0.000001)) { * //throw new ArgumentOutOfRangeException("CONCENTREER EENS!"); * }*/ // } end of removed check //throw new AccessViolationException("FOO"); //Console.WriteLine("ips["+ipi.ToString()+"]:"+ips[ipi].ToString()); //tip = trf.transformback(ips[ipi])+this.loc; tip = ips[ipi].copy(); tip.loc = trf.transformback(ips[ipi].loc) + this.loc; tip.flatshape.plane = trf.transformback(tip.flatshape.plane); //Console.WriteLine("___3"); /*if (!traceline.throughLocation(tip.loc, 0.0001)) { * throw new ArgumentOutOfRangeException(tip.loc.trico() + " (transformed) not in line " + traceline); * } else { * }*/ if (this.cborder.contains(tip.loc) || !checkBorder) //is this location within the borders between which the //parabolic mirror exists? { retips[ipi] = tip; /* //below for debug purposes only * retips[ipi] = new IntersectionPoint(traceline.startingpoint+ * traceline.direction.toLocation()*(traceline.direction.dotProduct(tip.loc-traceline.startingpoint)) * , tip.plane);*/ } else { //Console.WriteLine(tip.loc.ToString() + " is NOT within the cborder range-> "+this.cborder); retips[ipi] = null; continue; } //Console.WriteLine("trf: "+trf.ToString()); //Console.WriteLine("retips["+ipi.ToString()+"]:"+retips[ipi].ToString()); } return(retips); }
public void initNewIntersection(Scientrace.Line traceline, Scientrace.IntersectionPoint[] ips, Scientrace.Object3d object3d, bool bothdirections) { this.object3d = object3d; //Console.WriteLine("New Intersection with "+ips.Length+" IP's - "+object3d.hasParent()); this.intersects = false; //Console.WriteLine("FALSE"); foreach (Scientrace.IntersectionPoint ip in ips) { if (ip == null) { //Console.WriteLine("<NULL>"); continue; } //if bothdirections == true the Intersection does not nessicarily have to be away (in direction "direction") // from the startingpoint. if (!bothdirections) { //check if ip is in the line of the trace from its startingpoint if (traceline.direction.dotProduct(ip.loc-traceline.startingpoint) <= 1E-9) { //Console.WriteLine("WARNING: Intersectionpoint "+ip.loc.ToString()+" lies in the past @ "+traceline.startingpoint); continue; } } if (this.intersects == false) { //Console.WriteLine("TRUE"); this.intersects = true; this.enter = ip; this.exit = null; // new IntersectionPoint(null, null); CHANGED (BUGFIX?) BY JBC @ 20131205 continue; } if (this.enter.loc.distanceTo(traceline.startingpoint) > ip.loc.distanceTo(traceline.startingpoint)) { //this intersectionpoint is closer than the "enterpoint so far" // this condition is wrong right? if (this.exit==null) { this.exit = this.enter; // this is wrong right? } this.enter = ip; continue; } else { if (this.exit == null) { this.exit = ip; continue; } else { //this intersectionpoint is further from beam than enterpoint. New exitpoint defined. if (this.exit.loc.distanceTo(traceline.startingpoint) > ip.loc.distanceTo(traceline.startingpoint)) { //intersectionpoint is closer than old exitpoint this.exit = ip; continue; }} continue; // <-- existing exitpoint is closer than new IP: do nothing. } } }
/// <summary> /// "line" has to be transformed so it encounters the 2nd order polynominal with /// its base at 0,0,0 and orientation in 0,0,1 (z-direction) /// </summary> /// <param name="line"> /// A <see cref="Scientrace.Line"/> /// </param> public IntersectionPoint[] baseintersections(Scientrace.Line line) { // location = line.loc * (d * line.dir); // keep formulae readable double d1, d2, dx, dy, dz, c, lx, ly, lz; double ABCa, ABCb, ABCc, discr; Scientrace.Vector v1, v2; Scientrace.IntersectionPoint[] ip; c = this.c; dx = line.direction.x; dy = line.direction.y; dz = line.direction.z; lx = line.startingpoint.x; ly = line.startingpoint.y; lz = line.startingpoint.z; ABCa = c * (Math.Pow(dy, 2) + Math.Pow(dx, 2)); ABCb = (2 * c * (dy * ly + dx * lx)) - dz; ABCc = (c * (Math.Pow(ly, 2) + Math.Pow(lx, 2))) - lz; /*if ((dx*dy) == 0) { * ip = new Scientrace.IntersectionPoint[1]; * v1 = new Vector(lx, ly, c*(Math.Pow(lx, 2)+Math.Pow(ly, 2))); * ip[0] = new IntersectionPoint(v1.toLocation(), this.intersectionPlane(v1.x, v1.y)); * //ip[1] = null; * return ip; * }*/ // if ((Math.Pow(ABCa,2)) < 1E-56) { // <-- used to be // if ((Math.Pow(ABCa,2)) < 1E-31) { // <-- used to be if ((Math.Pow(ABCa, 2)) < 1E-31) // <-- now, so no (/less) significance errors do occur any longer in results //Console.WriteLine("ABCa is SMALL"+ABCa.ToString()); { ip = new Scientrace.IntersectionPoint[1]; d1 = -ABCc / ABCb; v1 = (line.direction.toVector() * d1) + line.startingpoint.toVector(); ip[0] = new IntersectionPoint(v1.toLocation(), this.baseIntersectionShape(v1.x, v1.y)); return(ip); } //Console.WriteLine("ABCa is large enough "+ABCa.ToString()); //d1,2 => lambda 1,2 at http://amswiki.jbos.eu/wiki/index.php/Parabolic_Collision#Quadratic_formula //derived from the quadratic formula, note the +/- sign before the Sqrt. discr = Math.Pow(ABCb, 2) - (4 * ABCa * ABCc); if (discr < 0) { //Console.WriteLine("Negative discriminant : "+discr); ip = new Scientrace.IntersectionPoint[0]; //ip[0] = null; //ip[1] = null; return(ip); } if (discr == 0) { ip = new Scientrace.IntersectionPoint[1]; d1 = ((-ABCb) + Math.Sqrt(Math.Pow(ABCb, 2) - (4 * ABCa * ABCc))) / (2 * ABCa); v1 = (line.direction.toVector() * d1) + line.startingpoint.toVector(); ip[0] = new IntersectionPoint(v1.toLocation(), this.baseIntersectionShape(v1.x, v1.y)); return(ip); } //still here? two results! /*d1 = ((-ABCb)+Math.Sqrt(Math.Pow(ABCb, 2)-(4*ABCa*ABCc)))/(2*ABCa); * d2 = ((-ABCb)-Math.Sqrt(Math.Pow(ABCb, 2)-(4*ABCa*ABCc)))/(2*ABCa);*/ d1 = ((-ABCb) + Math.Sqrt(discr)) / (2.0 * ABCa); d2 = ((-ABCb) - Math.Sqrt(discr)) / (2.0 * ABCa); v1 = (line.direction.toVector() * d1) + line.startingpoint.toVector(); v2 = (line.direction.toVector() * d2) + line.startingpoint.toVector(); //Console.WriteLine("discr: "+discr+" ABCa: "+ABCa+" ABCb: "+ABCb+" ABCc: "+ABCc); //FOR BETTER PERFORMANCE REMOVE CHECKS BELOW /* //This was removed at 20160222 * if ((v1 != null) && (!line.throughLocation(v1.toLocation(), 0.00001))) { * throw new Exception("TRFd line 1 "+v1.trico()+" avoids "+line.ToString()); * } * if ((v2 != null) && (!line.throughLocation(v2.toLocation(), 0.00001))) { * v2 = v1; * // Console.WriteLine("discr: "+discr); * // throw new Exception("TRFd line 2 "+v1.trico()+" avoids "+line.ToString()+" contrairy to "+v1.trico()); * } */ ip = new Scientrace.IntersectionPoint[2]; ip[0] = (v1 == null ? null : new IntersectionPoint(v1.toLocation(), this.baseIntersectionShape(v1.x, v1.y)) ); ip[1] = (v2 == null ? null : new IntersectionPoint(v2.toLocation(), this.baseIntersectionShape(v2.x, v2.y)) ); return(ip); }