public Angle(Scientrace.Trace fromTrace, Scientrace.Trace toTrace, Scientrace.Intersection intersection) { this.fromTrace = fromTrace; this.toTrace = toTrace; this.radians = fromTrace.traceline.direction.angleWith(toTrace.traceline.direction); this.intersection = intersection; }
public Angle(Scientrace.Trace fromTrace, Scientrace.Trace toTrace, Scientrace.Intersection intersection) { this.fromTrace = fromTrace; this.toTrace = toTrace; this.radians = fromTrace.traceline.direction.angleWith(toTrace.traceline.direction); this.intersection = intersection; }
public Scientrace.Trace createFullInternalReflectedTraceFork(Scientrace.Intersection intersection) { Scientrace.Trace fullReflectTrace = this.fork("_fR"); fullReflectTrace.traceline = fullReflectTrace.reflectAt(intersection.enter.flatshape.plane); fullReflectTrace.traceid = fullReflectTrace.traceid + "r"; fullReflectTrace.traceline.startingpoint = intersection.enter.loc; fullReflectTrace.nodecount++; //Console.WriteLine("INTERNAL REFLECTION! direction = "+newtrace.traceline.direction.trico()+this.currentObject.GetType()); return(fullReflectTrace); }
/// <summary> /// Prolong the trace to the specified Object3d instance (toObject3d) at location as specified in intersection. /// Prolonging does NOT increase the nodecounter. Attached objects count as 1 node alltogether. /// </summary> /// <param name='toObject3d'> /// The Object3d instance of interaction with the current Object3d at the surface. /// </param> /// <param name='intersection'> /// The intersection instance that describes the intersection that is calculated to occur. /// </param> public List <Scientrace.Trace> prolong(Scientrace.Object3d toObject3d, Scientrace.Intersection intersection) { Scientrace.Trace newtrace = this.clone(); List <Scientrace.Trace> newTraces = new List <Scientrace.Trace>(); newtrace.currentObject = toObject3d; newtrace.traceline.startingpoint = intersection.enter.loc; newtrace.traceline.direction = this.traceline.direction; newTraces.Add(newtrace); return(newTraces); }
public Scientrace.Intersection realIntersections(Scientrace.Trace trace, bool checkborder) { // check whether trace goes through cborder first for performance reasons Scientrace.Intersection intr; //if (this.cborder.crosses(trace)) { Scientrace.IntersectionPoint[] tips = this.realIntersections(trace.traceline, checkborder); intr = new Scientrace.Intersection(trace, tips, this); //}/ else { // intr = new Intersection(false, this); //} return(intr); }
} // end func. redirect public List <Scientrace.Trace> partialReflectRefract(Scientrace.Object3d fromObject3d, Scientrace.Object3d toObject3d, Scientrace.Intersection intersection, UnitVector surfaceNormal) { /*double oldrefindex = fromObject3d.materialproperties.refractiveindex(this); * double newrefindex = toObject3d.materialproperties.refractiveindex(this);*/ List <Scientrace.Trace> newTraces = new List <Trace>(); Scientrace.Trace refractTrace = this.fork("_pr"); refractTrace.currentObject = toObject3d; refractTrace.traceline.startingpoint = intersection.enter.loc; Scientrace.UnitVector normal = intersection.enter.flatshape.plane.getNorm() .orientedAgainst(this.traceline.direction) .tryToUnitVector(); // Evaluate absorption by toObject3d refractTrace.absorpByObject(toObject3d, normal, fromObject3d); if (refractTrace.isEmpty()) { newTraces.Add(refractTrace); return(newTraces); } // CHECK whether (partial) reflection occurs... if ((toObject3d.materialproperties.reflects) || ((intersection.leaving) && (fromObject3d.materialproperties.reflects))) { //double refcoef = toObject3d.materialproperties.reflection(refractTrace, surfaceNormal, this.currentObject); double refcoef = toObject3d.materialproperties.reflection(refractTrace, surfaceNormal, fromObject3d.materialproperties); Scientrace.Trace reflectTrace = refractTrace.fork("_R"); //.clone(); reflectrace.nodecount++; reflectTrace.intensity = refractTrace.intensity * refcoef; //intensity shouldn't spawn nor disappear here refractTrace.intensity = refractTrace.intensity - reflectTrace.intensity; //Scientrace.Spot normspot = new Scientrace.Spot(norm.toLocation()+intersection.enter.loc, null, 1); //CHANGED 20131030 //reflectrace.traceline = newtrace.reflectAt(intersection.enter.flatshape.plane); reflectTrace.traceline = refractTrace.reflectLineAbout(reflectTrace.traceline, surfaceNormal); //ADDED @ 20130122: the parial internal reflected trace should have the current object as oldobject. reflectTrace.currentObject = this.currentObject; //CURRENT OBJECT DOES NOT CHANGE FOR (partial)INTERNAL REFLECTION! newTraces.Add(reflectTrace); } this.initCreatedRefractTrace(refractTrace, surfaceNormal, fromObject3d, toObject3d); newTraces.Add(refractTrace); return(newTraces); } // end func partialReflectRefract
/// <summary> /// After an inventory of the first next intersection has been made, the trace has to "cross" it. /// This could mean that the trace is continued/prolonged, but it could also reflect or refract /// which is processed inside the "redirect" method. /// </summary> /// <param name='anIntersection'> /// An intersection. /// </param> public List <Scientrace.Trace> processIntersection(Scientrace.Intersection anIntersection) { // basic check on validity if (this.isEmpty()) { Console.WriteLine("invisible trace found. Should have died earlier. Now terminating."); throw new Exception("invisible trace"); /*return;*/ } /* OBSOLETE: Done by "trace::cycle()" method already. * // if the intersection states that the object is left set the parent object as intersection * //intersection.resetToParentObjectWhenLeaving(); */ //Console.WriteLine("INTERSECTION REPORT: \n"+anIntersection.ToString()); // another basic check if object3d is set if (anIntersection.object3d == null) { throw new ArgumentNullException("intersection.object3d", "AN ERROR OCCURRED. UNKNOWN OBJECT " + anIntersection.intersects.ToString()); } List <Scientrace.Trace> newTraces; // there any interaction at the intersection? if (anIntersection.object3d.attachedTo(this.currentObject)) // do not interact between attached objects { newTraces = this.prolong(anIntersection.object3d, anIntersection); //DO NOT ADD ANGLES TO JOURNAL FOR PROLOGING: // TraceJournal.Instance.addAngle(new Scientrace.Angle(this, newtrace, intersection)); } else { // redirect on volume-change while intersecting //***newtrace = this.redirect(currentObj, intersection); newTraces = this.redirect(anIntersection.object3d, anIntersection); foreach (Scientrace.Trace newtrace in newTraces) { TraceJournal.Instance.recordAngle(new Scientrace.Angle(this, newtrace, anIntersection)); } } //get rid of "this" old trace, traces in newTraces (if any) are the new traces this.perish(anIntersection.enter.loc); //let the new traces cycle instead foreach (Scientrace.Trace newtrace in newTraces) { newtrace.cycle(); } return(newTraces); }
} //end string exportX3D(env) public override Intersection intersects(Trace aTrace) { // Finding intersectionpoints at spheres Scientrace.Intersection sphere1Intersections = this.dummySphere1.intersects(aTrace); Scientrace.Intersection sphere2Intersections = this.dummySphere2.intersects(aTrace); /* No sphere intersections at all? */ if (!sphere1Intersections.intersects && !sphere2Intersections.intersects) { return(Intersection.notIntersect(this)); } List <IntersectionPoint> iplist = new List <IntersectionPoint>(); //conditional &&'s, locations are only probed if existing if ((sphere1Intersections.enter != null) && this.dummySphere2.contains(sphere1Intersections.enter.loc)) { iplist.Add(sphere1Intersections.enter); } if ((sphere1Intersections.exit != null) && this.dummySphere2.contains(sphere1Intersections.exit.loc)) { iplist.Add(sphere1Intersections.exit); } if ((sphere2Intersections.enter != null) && this.dummySphere1.contains(sphere2Intersections.enter.loc)) { iplist.Add(sphere2Intersections.enter); } if ((sphere2Intersections.exit != null) && this.dummySphere1.contains(sphere2Intersections.exit.loc)) { iplist.Add(sphere2Intersections.exit); } /* No valid intersections? */ if (iplist.Count < 1) { return(Intersection.notIntersect(this)); } Scientrace.IntersectionPoint[] ips = iplist.ToArray(); 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 TestCylinderIntersects() { Scientrace.InfiniteCylinderBorder icb = new Scientrace.InfiniteCylinderBorder(null, null, new Scientrace.Location(0, -14.5, 0), new Scientrace.UnitVector(0, 0, 1), 0.2); Scientrace.Line testLine = new Scientrace.Line(0, 0, 0, 0, -1, 0); Scientrace.Intersection Ints = icb.intersects(new Scientrace.Trace(600, null, testLine, null, 1, 1)); Assert.AreEqual(Ints.enter.loc.ToCompactString(), new Scientrace.Location(0, -14.3, 0).ToCompactString()); Assert.AreEqual(Ints.exit.loc.ToCompactString(), new Scientrace.Location(0, -14.7, 0).ToCompactString()); testLine = new Scientrace.Line(0, 0, 0.1, 0, -1, 0); Ints = icb.intersects(new Scientrace.Trace(600, null, testLine, null, 1, 1)); Assert.AreEqual(Ints.enter.loc.ToCompactString(), new Scientrace.Location(0, -14.3, 0.1).ToCompactString()); Assert.AreEqual(Ints.exit.loc.ToCompactString(), new Scientrace.Location(0, -14.7, 0.1).ToCompactString()); testLine = new Scientrace.Line(0.1, 0, 0, 0, -1, 0); Ints = icb.intersects(new Scientrace.Trace(600, null, testLine, null, 1, 1)); Assert.AreEqual(Ints.enter.loc.ToCompactString(), new Scientrace.Location(0.1, -14.5 + (Math.Sqrt(0.03)), 0).ToCompactString()); Assert.AreEqual(Ints.exit.loc.ToCompactString(), new Scientrace.Location(0.1, -14.5 - (Math.Sqrt(0.03)), 0).ToCompactString()); }
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(Trace trace) { Scientrace.Intersection firstIntersection = new Scientrace.Intersection(false, null); Scientrace.Intersection currentintersection = new Scientrace.Intersection(false, null); double?firstdistance = null; double currentdistance; SortedList slobjects = new SortedList(); //Console.WriteLine(this.tag+" HAS "+this.objects.Count+ " o3ds"); //copying (by reference of course) all objects to a sortedlist. foreach (Object3d iobject3d in this.objects) { //Console.WriteLine("POKING "+ iobject3d.tag); slobjects.Add(iobject3d.parseOrder, iobject3d); } foreach (DictionaryEntry deObject3d in slobjects) { Object3d iObject = (Object3d)deObject3d.Value; //validating currentintersection: currentintersection = iObject.intersectsBefore(trace, currentintersection); /*if (currentintersection==null) { continue; } * if (currentintersection.enter==null) { continue; } * if (currentintersection.exit==null) { continue; } */ //currentintersection = iObject.intersects(trace); /*foreach (Object3d iobject3d in this.objects) { * currentintersection = iobject3dl.intersects(trace);*/ REPARSE: if (!currentintersection.intersects) { continue; //no intersection with this object? Try next object in collection (continue) } if ((currentintersection.enter.loc - trace.traceline.startingpoint).dotProduct(trace.traceline.direction) < 0) { //Console.WriteLine("Found object lies in the past! Skipping "+iObject.tag); continue; } // else {Console.WriteLine("not in the past, but :"+(currentintersection.enter.loc-trace.traceline.startingpoint).dotProduct(trace.traceline.direction));} currentdistance = currentintersection.enter.loc.distanceTo(trace.traceline.startingpoint); if (currentintersection.object3d == trace.currentObject) { /* If you're inside an object and the beam meets the same object, * it should only have an "enterloc" which is where the beam "leaves" the object. */ if (currentintersection.exit != null) // .loc part after exit removed at 20131205 /* perhaps the intersection has found the object at the same starting point */ { if (currentintersection.enter.loc.distanceTo(trace.traceline.startingpoint) < trace.getMinDistinctionLength()) { Console.WriteLine("New functionality: removing exit for " + currentintersection.object3d.tag); currentintersection.removeExit(); goto REPARSE; } /* check this occuring warning out after internal reflections. Doesn't * seem to cause any problems though. */ if (currentintersection.object3d != trace.currentObject) // because if they are the same it seems like internal reflection { Console.WriteLine("WARNING @" + this.tag + ": Collision (" + currentintersection.object3d.tag + ")" + " with current object (" + trace.currentObject.tag + ")" + " without leaving first \n-----\n" + trace.ToCompactString() + "\nentering: " + currentintersection.enter.loc.trico() + "\nexit:" + currentintersection.exit.loc.tricon() + "-----"); } //endif (currentintersection.object3d != trace.currentObject) continue; /* else: if no exit location is set, we must be leaving the current object at "enter" */ } else // Leaving the current object should return to the parent collection (environment?). { currentintersection.leaving = true; } /* else: if the colliding object isn't the current object */ } else { // analogue as above but inverted: you cannot leave an object you're not inside. if (currentintersection.exit == null) // .loc part after exit removed at 20131205 //or can you? //continue; NO LONGER ABORT PARSING HERE, BECAUSE: //CONCLUSION: //YES YOU CAN, think about an object within an object or a reflective layer { if (currentintersection.object3d.hasVolume) { //Console.WriteLine("Leaving object with volume("+currentintersection.object3d.tag+"), but don't refract"); continue; } } } if (!firstIntersection.intersects) { firstIntersection = currentintersection; firstdistance = firstIntersection.enter.loc.distanceTo(trace.traceline.startingpoint); continue; } /* below a firstInteraction is already set */ currentdistance = currentintersection.enter.loc.distanceTo(trace.traceline.startingpoint); if (firstIntersection.leaving) { /* in order to make "attached objects" change into one another the * colliding object has to be found instead of the "leaving" border. */ /* object which are seperated from each other with less than the lights wavelength * will be treated as connected to each other. Not first leaving previous border */ if (currentdistance - firstdistance < trace.getMinDistinctionLength()) { firstIntersection = currentintersection; firstdistance = currentdistance; continue; } continue; } /* if (firstdistance == null) { * throw new NullReferenceException("firstdistance not set"); * } *///this shouldn't occur and doesn't, so not checking anymore if (firstdistance > currentdistance) { firstdistance = currentdistance; firstIntersection = currentintersection; continue; } /* TODO for optimization purposes: * find whether any "containing" object is intersected, find first and return an Intersection */ } /*if (firstIntersection.leaving) { * //Console.WriteLine("----------> leaving *** "+currentintersection.object3d); * }*/ return(firstIntersection); }
public override Intersection intersects(Trace aTrace) { // Finding intersectionpoints at spheres Scientrace.Intersection sphere1Intersections = this.dummySphere1.intersects(aTrace); Scientrace.Intersection sphere2Intersections = this.dummySphere2.intersects(aTrace); /* No sphere intersections at all? */ if (!sphere1Intersections.intersects && !sphere2Intersections.intersects) { return Intersection.notIntersect(this); } List<IntersectionPoint> iplist = new List<IntersectionPoint>(); //conditional &&'s, locations are only probed if existing if ((sphere1Intersections.enter!=null) && this.dummySphere2.contains(sphere1Intersections.enter.loc)) { iplist.Add(sphere1Intersections.enter); } if ((sphere1Intersections.exit!=null) && this.dummySphere2.contains(sphere1Intersections.exit.loc)) { iplist.Add(sphere1Intersections.exit); } if ((sphere2Intersections.enter!=null) && this.dummySphere1.contains(sphere2Intersections.enter.loc)) { iplist.Add(sphere2Intersections.enter); } if ((sphere2Intersections.exit!=null) && this.dummySphere1.contains(sphere2Intersections.exit.loc)) { iplist.Add(sphere2Intersections.exit); } /* No valid intersections? */ if (iplist.Count < 1) { return Intersection.notIntersect(this); } Scientrace.IntersectionPoint[] ips = iplist.ToArray(); 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; }
// return type changed from single Scientrace.Trace instance to List<Scientrace.Trace> newTraces in order to better facilitate the splitting of traces. public List <Scientrace.Trace> redirect_without_polarisation(Scientrace.Object3d toObject, Scientrace.Intersection intersection) { List <Scientrace.Trace> newTraces = new List <Trace>(); //what objects are acting here? Scientrace.Object3d fromObject = this.currentObject; /* The "normal" vector should always point towards the incoming beam when * using the Snellius-approach as described by figure 15 in * "Optical simulation of the SunCycle concentrator using Scientrace" * by Joep Bos-Coenraad (2013) */ Scientrace.UnitVector normal = intersection.enter.flatshape.plane.getNorm() .orientedAgainst(this.traceline.direction) .tryToUnitVector(); //Does full internal reflection occur? if (this.fullInternalReflects(normal, fromObject, toObject)) { //construct reflectedTrace Trace internalReflectedTrace = this.createFullInternalReflectedTraceFork(intersection); newTraces.Add(internalReflectedTrace); // in case of full internal reflection, no other "effects" occur, so return the newTraces collection here. return(newTraces); } newTraces.AddRange(this.partialReflectRefract(fromObject, toObject, intersection, normal)); // HERE USED TO BE CODE THAT CHECKED WHETHER (based on alphadirection) the direction of the incoming beam was altered at all. return(newTraces); } // end func. redirect
public override Intersection intersects(Trace trace) { Scientrace.Intersection firstIntersection = new Scientrace.Intersection(false, null); Scientrace.Intersection currentintersection = new Scientrace.Intersection(false, null); double? firstdistance = null; double currentdistance; SortedList slobjects = new SortedList(); //Console.WriteLine(this.tag+" HAS "+this.objects.Count+ " o3ds"); //copying (by reference of course) all objects to a sortedlist. foreach (Object3d iobject3d in this.objects) { //Console.WriteLine("POKING "+ iobject3d.tag); slobjects.Add(iobject3d.parseOrder, iobject3d); } foreach (DictionaryEntry deObject3d in slobjects) { Object3d iObject = (Object3d)deObject3d.Value; //validating currentintersection: currentintersection = iObject.intersectsBefore(trace, currentintersection); /*if (currentintersection==null) { continue; } if (currentintersection.enter==null) { continue; } if (currentintersection.exit==null) { continue; } */ //currentintersection = iObject.intersects(trace); /*foreach (Object3d iobject3d in this.objects) { currentintersection = iobject3dl.intersects(trace);*/ REPARSE: if (!currentintersection.intersects) { continue; //no intersection with this object? Try next object in collection (continue) } if ((currentintersection.enter.loc-trace.traceline.startingpoint).dotProduct(trace.traceline.direction) < 0) { //Console.WriteLine("Found object lies in the past! Skipping "+iObject.tag); continue; }// else {Console.WriteLine("not in the past, but :"+(currentintersection.enter.loc-trace.traceline.startingpoint).dotProduct(trace.traceline.direction));} currentdistance = currentintersection.enter.loc.distanceTo(trace.traceline.startingpoint); if (currentintersection.object3d == trace.currentObject) { /* If you're inside an object and the beam meets the same object, * it should only have an "enterloc" which is where the beam "leaves" the object. */ if (currentintersection.exit != null) { // .loc part after exit removed at 20131205 /* perhaps the intersection has found the object at the same starting point */ if (currentintersection.enter.loc.distanceTo(trace.traceline.startingpoint) < trace.getMinDistinctionLength()) { Console.WriteLine("New functionality: removing exit for "+currentintersection.object3d.tag); currentintersection.removeExit(); goto REPARSE; } /* check this occuring warning out after internal reflections. Doesn't * seem to cause any problems though. */ if (currentintersection.object3d != trace.currentObject) { // because if they are the same it seems like internal reflection Console.WriteLine("WARNING @"+this.tag+": Collision ("+currentintersection.object3d.tag+")"+ " with current object ("+trace.currentObject.tag+")"+ " without leaving first \n-----\n"+ trace.ToCompactString()+ "\nentering: "+currentintersection.enter.loc.trico()+ "\nexit:"+currentintersection.exit.loc.tricon()+"-----"); } //endif (currentintersection.object3d != trace.currentObject) continue; /* else: if no exit location is set, we must be leaving the current object at "enter" */ } else { // Leaving the current object should return to the parent collection (environment?). currentintersection.leaving = true; } /* else: if the colliding object isn't the current object */ } else { // analogue as above but inverted: you cannot leave an object you're not inside. if (currentintersection.exit == null) { // .loc part after exit removed at 20131205 //or can you? //continue; NO LONGER ABORT PARSING HERE, BECAUSE: //CONCLUSION: //YES YOU CAN, think about an object within an object or a reflective layer if (currentintersection.object3d.hasVolume) { //Console.WriteLine("Leaving object with volume("+currentintersection.object3d.tag+"), but don't refract"); continue; } } } if (!firstIntersection.intersects) { firstIntersection = currentintersection; firstdistance = firstIntersection.enter.loc.distanceTo(trace.traceline.startingpoint); continue; } /* below a firstInteraction is already set */ currentdistance = currentintersection.enter.loc.distanceTo(trace.traceline.startingpoint); if (firstIntersection.leaving) { /* in order to make "attached objects" change into one another the * colliding object has to be found instead of the "leaving" border. */ /* object which are seperated from each other with less than the lights wavelength * will be treated as connected to each other. Not first leaving previous border */ if (currentdistance - firstdistance < trace.getMinDistinctionLength()) { firstIntersection = currentintersection; firstdistance = currentdistance; continue; } continue; } /* if (firstdistance == null) { throw new NullReferenceException("firstdistance not set"); } */ //this shouldn't occur and doesn't, so not checking anymore if (firstdistance > currentdistance) { firstdistance = currentdistance; firstIntersection = currentintersection; continue; } /* TODO for optimization purposes: * find whether any "containing" object is intersected, find first and return an Intersection */ } /*if (firstIntersection.leaving) { //Console.WriteLine("----------> leaving *** "+currentintersection.object3d); }*/ return firstIntersection; }
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; }
// return type changed from single Scientrace.Trace instance to List<Scientrace.Trace> newTraces in order to better facilitate the splitting of traces. public List<Scientrace.Trace> redirect_with_polarisation(Scientrace.Object3d toObject, Scientrace.Intersection intersection) { List<Scientrace.Trace> newTraces = new List<Trace>(); //what objects are acting here? Scientrace.Object3d fromObject = this.currentObject; /* The "normal" vector should always point towards the incoming beam when * using the Snellius-approach as described by figure 15 in * "Optical simulation of the SunCycle concentrator using Scientrace" * by Joep Bos-Coenraad (2013) */ Scientrace.UnitVector normal = intersection.enter.flatshape.plane.getNorm() .orientedAgainst(this.traceline.direction) .tryToUnitVector(); DielectricSurfaceInteraction fsi = new DielectricSurfaceInteraction(this, intersection.enter.loc, normal, fromObject.materialproperties.refractiveindex(this), toObject.materialproperties.refractiveindex(this), toObject); newTraces.AddIfNotNull(fsi.getReflectTrace(this.getMinDistinctionLength())); newTraces.AddIfNotNull(fsi.getRefractTrace(this.getMinDistinctionLength())); return newTraces; }
/// <summary> /// The Cycle is actually the main action for a trace. If you start somewhere in /// space with components, with a trace with a direction, what components do you /// encounter? How does the trace interact? It starts new traces that cycles in /// turn, or it might just "end" due to absorption, a max. number of interactions, /// too low intensity, whatever. /// </summary> public void cycle() { // Does cycling still makes sense? If not: don't. if (!this.alive || this.isEmpty()) { return; } bool retry = false; // Find intersections Scientrace.Intersection unmod_intersection = this.lightsource.env.intersects(this); // Is there an intersection? (an object with a surface in this trace's path? if (unmod_intersection.intersects) { /* Linear Modifiers are applied. This may cause the intersection to produce a surface with a normal that * has an orientation in the opposite direction of the incoming beam. This is not allowed. When this is * the case, a new modification is performed on the raw intersection until this is OK. */ // TODO: create a "safe" applyLinearModifiers method which performs this operation on a ref vector attribute. Scientrace.Intersection active_intersection = new Scientrace.Intersection(unmod_intersection); if (active_intersection.hasSurfaceNormalModifiers()) { do { if (retry) { active_intersection = new Scientrace.Intersection(unmod_intersection); //Console.WriteLine("\n+1\n"); } retry = true; // Intoduce modelled surface alterations, e.g. to simulate imperfections. active_intersection.applyLinearModifiers(); //this.debug_IntersectionValuesToConsole(unmod_intersection, active_intersection); }while (!this.validFlatPlaneModification(unmod_intersection, active_intersection)); } // Any new intersection should lie in the line of the direction of the traceline from the startingpoint. Doublecheck: if ((active_intersection.enter.loc - this.traceline.startingpoint).dotProduct(this.traceline.direction) < 0) { throw new Exception("location lies in the past!"); } // FUNCTIONAL PROCEDURES ON TRACE CYCLING // If the trace is leaving the current component... if (active_intersection.leaving) { active_intersection.resetObjectToParentWhenLeaving(); } //List<Scientrace.Trace> newTraces = this.processIntersection(active_intersection); /* if (active_intersection.hasSurfaceNormalModifiers()) { * foreach (Trace atrace in newTraces) { * if (atrace.intensityFraction() == 0) * continue; * Console.WriteLine("\n\nTrace: "+this.ToCompactString()); * Console.WriteLine("ToTrace ("+newTraces.Count+"): "+atrace.ToCompactString()); * //Console.WriteLine("Intensity/isalive:"+atrace.intensityFraction()+"/"+atrace.alive); * Console.WriteLine("New angle with Old normal: "+(atrace.traceline.direction.angleWith(active_intersection.enter.flatshape.plane.getNorm())*180/Math.PI).ToString()+"@ "+active_intersection.object3d.tag); * Console.WriteLine("New angle with New normal: "+(atrace.traceline.direction.angleWith(unmod_intersection.enter.flatshape.plane.getNorm())*180/Math.PI).ToString()); * * Console.WriteLine("-Old angle with New normal: "+(this.traceline.direction.angleWith(active_intersection.enter.flatshape.plane.getNorm())*180/Math.PI).ToString()+"@ "+active_intersection.object3d.tag); * Console.WriteLine("-Old angle with Old normal: "+(this.traceline.direction.angleWith(unmod_intersection.enter.flatshape.plane.getNorm())*180/Math.PI).ToString()); * } * }*/ } else { /*no intersection before border? End the trace at the border of the environment */ if (this.lightsource.env.perishAtBorder) { //draws last line to the end of the environment, this function also perishes this trace. this.lightsource.env.traceLeavesEnvironment(this); } else { this.perishQuietly(); } } // end "if not intersects" } // end Cycle method
public Scientrace.Intersection intersectplanesforobject(Scientrace.Object3d anObject, List <Scientrace.FlatShape2d> pgrams) { Scientrace.Trace trace = this; Scientrace.Location firstloc = null; Scientrace.FlatShape2d enterplane = null; Scientrace.Location lastloc = null; double?firstdistance = null; double?lastdistance = null; Scientrace.Location tloc; double tdistance; foreach (Scientrace.FlatShape2d pgram in pgrams) { tloc = pgram.atPath(trace.traceline); if (tloc == null) { continue; } if (((tloc - trace.traceline.startingpoint).dotProduct(trace.traceline.direction)) < trace.getMinDistinctionLength()) { continue; //the location (even if increased with one wavelength) is "behind" the trace } tdistance = tloc.distanceTo(trace.traceline.startingpoint); if (firstdistance == null) { //assign first and last to first item in collection firstdistance = tdistance; firstloc = tloc; enterplane = pgram; lastdistance = tdistance; lastloc = tloc; } if (tdistance < firstdistance) { //Console.WriteLine(tdistance.ToString()+"<"+firstdistance.ToString()); firstdistance = tdistance; firstloc = tloc; enterplane = pgram; } if (tdistance > lastdistance) { //Console.WriteLine("We have a large distance gentlemen"); lastdistance = tdistance; lastloc = tloc; } } //end of pgrams-for-loop if (firstdistance == null) { //when no side of the paralellogram has been intersected return(new Scientrace.Intersection(false, anObject)); } if (firstdistance == lastdistance) { lastdistance = null; lastloc = null; } if (lastdistance == null) { //Console.WriteLine("I have no ending"); } else { //Console.WriteLine("I from "+trace.currentObject.GetType()+" @ "+trace.traceline.startingpoint.trico()+" pass through an object"); } Scientrace.Intersection intrs = new Scientrace.Intersection(true, anObject, firstloc, enterplane, lastloc); intrs.leaving = (lastloc == null); return(intrs); }
public List <Scientrace.Trace> redirect(Scientrace.Object3d toObject, Scientrace.Intersection intersection) { return((toObject.materialproperties.dielectric && Trace.support_polarisation) ? this.redirect_with_polarisation(toObject, intersection) // the new implementation : this.redirect_without_polarisation(toObject, intersection)); // the old implementation }