예제 #1
0
 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;
 }
예제 #2
0
파일: Angle.cs 프로젝트: JoepBC/scientrace
 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;
 }
예제 #3
0
 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);
 }
예제 #4
0
        /// <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);
        }
예제 #5
0
 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);
 }
예제 #6
0
        }         // 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
예제 #7
0
        /// <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);
        }
예제 #8
0
        }         //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());
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
        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;
        }
예제 #13
0
        // 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
예제 #14
0
        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;
        }
예제 #15
0
        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;
        }
예제 #16
0
	// 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;
		}
예제 #17
0
        /// <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
예제 #18
0
        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);
        }
예제 #19
0
 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
 }