/*
 *              Scientrace.CircularFresnelPrism cprism = new Scientrace.CircularFresnelPrism(env, air,
 *                      new Location(0, 0, 0), new NonzeroVector(prismradius, 0, 0).rotateAboutY(prismAngleRadians),
 *                      new NonzeroVector(0,0, prismradius).rotateAboutY(prismAngleRadians), new NonzeroVector(0, -0.5E-2, 0),
 *                      this.prism_angle*Math.PI/180, (Math.PI/2)-(this.prism_angle*Math.PI/180), dentalcount, pmma);
 *?/
 *
 *      /* Prism and Mirror data from configfile */
        public Scientrace.ParabolicMirror parseXParabolicMirror(XElement xmir)
        {
            Scientrace.UnitVector miraxis = this.X.getXNzVector(xmir.Element("MirrorAxis")).toUnitVector();

            /*string materialid = this.X.getXString(xmir.Attribute("Material"));
             * Scientrace.MaterialProperties material = Scientrace.MaterialProperties.FromIdentifier(materialid);*/
            Scientrace.MaterialProperties material = new ShadowClassConstruct(this.parentcollection).getXMaterial(xmir);
            XMLBorderParser xbp = new XMLBorderParser();

            Scientrace.AbstractGridBorder border = xbp.getXBorder(xmir.Element("Border"));
            Scientrace.ParabolicMirror    tretpmir;
            if (xmir.Attribute("DistanceToMirror") == null)
            {
                double parabolic_constant    = this.X.getXDouble(xmir.Attribute("ParabolicConstant"));
                Scientrace.Location location = this.X.getXLocation(xmir.Element("Location"));
                tretpmir = new Scientrace.ParabolicMirror(
                    this.parentcollection, material, location, miraxis, parabolic_constant, border);
            }
            else
            {
                double distance_to_mirror      = this.X.getXDouble(xmir.Attribute("DistanceToMirror"));
                Scientrace.Location focuspoint = this.X.getXLocation(xmir.Element("FocusPoint"));
//				Console.WriteLine("-->"+focuspoint.tricoshort()+ " / "+ distance_to_mirror+miraxis.tricon()+ " / <---");
                tretpmir = Scientrace.ParabolicMirror.CreateAtFocus(this.parentcollection, material,
                                                                    focuspoint, distance_to_mirror, miraxis, border);
                tretpmir.exportX3Dgridsteps = 64;
            }
            return(tretpmir);
        }
        public void initCreatedRefractTrace(Trace refractTrace, UnitVector surfaceNormal, Scientrace.Object3d fromObject3d, Scientrace.Object3d toObject3d)
        {
            double oldrefindex = fromObject3d.materialproperties.refractiveindex(this);
            double newrefindex = toObject3d.materialproperties.refractiveindex(this);
            //for definitions on the parameters below, check fullInternalReflects function.

            UnitVector incoming_trace_direction = this.traceline.direction;
            if (incoming_trace_direction.dotProduct(surfaceNormal) > 0) {
            surfaceNormal = surfaceNormal.negative();
            }

            Scientrace.UnitVector nnorm = surfaceNormal.negative();
            Scientrace.Vector incoming_normal_projection = nnorm*(incoming_trace_direction.dotProduct(nnorm));
            Vector L1 = incoming_trace_direction-incoming_normal_projection;
            double L2 = (oldrefindex/newrefindex)*L1.length;

            if (incoming_trace_direction == incoming_normal_projection) {
            //in case of normal incident light: do not refract.
            refractTrace.traceline.direction = incoming_trace_direction;
            return;
            }

            try {
            refractTrace.traceline.direction = ((nnorm*Math.Sqrt(1 - Math.Pow(L2,2)))
                    +(L1.tryToUnitVector()*L2)).tryToUnitVector();
            } catch (ZeroNonzeroVectorException) {
                Console.WriteLine("WARNING: cannot define direction for refraction trace. Using surface normal instead. (L1: "+incoming_trace_direction.trico()+", L2:"+incoming_normal_projection.trico()+").");
                refractTrace.traceline.direction = nnorm;
            } //end try/catch
        }
        public InfiniteCylinderBorder(Scientrace.Object3dCollection parent, Scientrace.MaterialProperties mprops,
									Scientrace.Location loc, Scientrace.UnitVector direction, double radius)
            : base(parent, mprops)
        {
            this.direction = direction;
            this.radius = radius;
            this.loc = loc;
        }
        public Scientrace.Location traceLeavesEnvironment(Scientrace.Trace trace)
        {
            trace.currentObject = this;
            Scientrace.Line line = trace.traceline;
            UnitVector      dir  = line.direction;

            dir.check();
            Vector loc = line.startingpoint;

            /* find locations where line leaves a sphere of radius this.radius around 0,0,0
             * derivation:
             * r^2 = |l*dir + loc|^2
             * hence:
             * 0 = l^2 * |dir|^2 + 2*l*|dir.loc| + |loc|^2 - r^2    //the "." represents a dotproduct
             * Solve ABC formula for l:
             * a = |dir|^2
             * b = 2 * (loc . dir)
             * c = |loc|^2 - r^2 */
            double a            = Math.Pow(dir.x, 2) + Math.Pow(dir.y, 2) + Math.Pow(dir.z, 2);
            double b            = 2 * (loc.x * dir.x + loc.y * dir.y + loc.z * dir.z);
            double c            = Math.Pow(loc.x, 2) + Math.Pow(loc.y, 2) + Math.Pow(loc.z, 2) - (Math.Pow(this.radius, 2));
            double discriminant = Math.Pow(b, 2) - 4 * a * c;

            if (discriminant < 0)
            {
                throw new ArgumentOutOfRangeException("Trace leaves environment from within environment. Are the boundaries of your environment perhaps smaller than your objects?\n Environment radius: " + this.radius + "\n Trace data:" + trace.ToString());
            }
            //ABC formula
            double ans1 = (-b + Math.Sqrt(discriminant)) / (2 * a);
            double ans2 = (-b - Math.Sqrt(discriminant)) / (2 * a);
            double ans  = Math.Max(ans1, ans2);

            //Console.WriteLine("\n"+ans.ToString()+" * "+dir.trico()+"( = "+(dir*ans).trico()+") +"+loc.trico()+" = "+((dir*ans)+loc).toLocation().ToCompactString()+" is ...");
//			throw new AccessViolationException();
            //Console.WriteLine("IT ENDS HERE: "+((dir*Math.Max(ans1,ans2))+loc).toLocation().ToString());

            Scientrace.Location leavelocation = (dir * ans + loc).toLocation();

/*			Console.WriteLine("Direction: "+dir.trico()+
 *                              "ABS ANS: "+(Math.Pow(b,2) - 4* a*c)+
 *                              "Location: "+loc.trico());*/
            trace.perish(leavelocation);
            return(leavelocation);
        }
        public Scientrace.Rectangle parseXRectangleCenterConstructor(XElement xsc)
        {
            Scientrace.Location center = this.X.getXLocation(xsc.Element("Center"));
            //Scientrace.Location pointingtowards = this.X.getXLocation(xsc.Element("PointingTowards"));
            Scientrace.Location pointingtowards = this.X.getXLocation(xsc, "PointingTowards", (this.X.getXLocation(xsc, "Normal") + center));

            Scientrace.UnitVector orthogonaldir = this.X.getXVector(xsc.Element("OrthogonalDirection")).tryToUnitVector();
            //double sidelength = this.X.getXDouble(xsc.Attribute("SideLength"));
            double sidelength = this.X.getXDouble(xsc, "SideLength");

            /*string materialid = this.X.getXString(xsc.Attribute("Material"));
             * Scientrace.MaterialProperties material = Scientrace.MaterialProperties.FromIdentifier(materialid); */
            Scientrace.MaterialProperties material = new ShadowClassConstruct(this.parentcollection).getXMaterial(xsc);
            Scientrace.Rectangle          retcel   = new Scientrace.Rectangle(this.parentcollection, material, center,
                                                                              pointingtowards, orthogonaldir, sidelength);
            this.addCommonObjectProperties(retcel, xsc);
            this.registerObject(xsc, retcel);
            return(retcel);
        }
        /// <summary>
        /// Fulls the internal reflects.
        /// </summary>
        /// <returns>
        /// True if full internal reflection occurs. Returns false in case of refraction and partial reflection
        /// </returns>
        /// <param name='incoming_trace_direction'>
        /// incoming_trace_direction is the vector of the trace passing the surface 
        /// </param>
        public bool fullInternalReflects(UnitVector surfaceNormal, Scientrace.Object3d fromObject3d, Scientrace.Object3d toObject3d)
        {
            double oldrefindex = fromObject3d.materialproperties.refractiveindex(this);
            double newrefindex = toObject3d.materialproperties.refractiveindex(this);

            UnitVector incoming_trace_direction = this.traceline.direction;
            // make sure the surfaceNormal is directed towards the incoming beam (so in the opposite direction)
            if (incoming_trace_direction.dotProduct(surfaceNormal) > 0) {
            surfaceNormal = surfaceNormal.negative();
            }
            // nnorm is surface normale directed into the *new* surface, so *along* the incoming beam
            Scientrace.UnitVector nnorm = surfaceNormal.negative();
            // incoming_normal_projection is the projection of incoming_trace_direction at the (n)norm
            Scientrace.Vector incoming_normal_projection = nnorm*(incoming_trace_direction.dotProduct(nnorm));
            // L1 and L2 are defined as on figure 15 / page 20 from the "Optical simulation of the SunCycle concentrator using Scientrace (J. Bos-Coenraad 2013)
            Vector L1 = incoming_trace_direction-incoming_normal_projection;
            double L2 = (oldrefindex/newrefindex)*L1.length;
            // If L2 is larger than 1, full internal reflection takes place.
            return (L2 > 1);
        }
Example #7
0
 public override Scientrace.VectorTransform getGridTransform(UnitVector nz)
 {
     //construction on request
     if (this.gridtrf == null) {
     Scientrace.Vector refvec;
     //vector has to differ at least 1% from the orthogonal orientation.
     if (Math.Abs(directionlength.toUnitVector().dotProduct(nz))<0.99) {
         refvec = nz;
         } else {
         refvec = (nz.rotateAboutX(Math.PI/2).rotateAboutY(Math.PI/2)).tryToUnitVector();
         if (Math.Abs(directionlength.toUnitVector().dotProduct(nz))<0.99) {
             throw new Exception("WARNING: CrossProducts cannot produce orthogonal lines over two parallel " +
             "vectors, two vectors that are almost parallel will give a large significance error. FIX DIDN'T WORK, please contact the Scientrace developer.");
             }
         }
     Scientrace.NonzeroVector u, v;
     u = refvec.crossProduct(directionlength).tryToUnitVector()*this.radius;
     v = u.crossProduct(directionlength).tryToUnitVector()*this.radius;
     this.gridtrf = new Scientrace.VectorTransform(u,v,this.directionlength);
     }
     return this.gridtrf;
 }
Example #8
0
        /// <summary>
        /// Fulls the internal reflects.
        /// </summary>
        /// <returns>
        /// True if full internal reflection occurs. Returns false in case of refraction and partial reflection
        /// </returns>
        /// <param name='incoming_trace_direction'>
        /// incoming_trace_direction is the vector of the trace passing the surface
        /// </param>
        public bool fullInternalReflects(UnitVector surfaceNormal, Scientrace.Object3d fromObject3d, Scientrace.Object3d toObject3d)
        {
            double oldrefindex = fromObject3d.materialproperties.refractiveindex(this);
            double newrefindex = toObject3d.materialproperties.refractiveindex(this);

            UnitVector incoming_trace_direction = this.traceline.direction;

            // make sure the surfaceNormal is directed towards the incoming beam (so in the opposite direction)
            if (incoming_trace_direction.dotProduct(surfaceNormal) > 0)
            {
                surfaceNormal = surfaceNormal.negative();
            }
            // nnorm is surface normale directed into the *new* surface, so *along* the incoming beam
            Scientrace.UnitVector nnorm = surfaceNormal.negative();
            // incoming_normal_projection is the projection of incoming_trace_direction at the (n)norm
            Scientrace.Vector incoming_normal_projection = nnorm * (incoming_trace_direction.dotProduct(nnorm));
            // L1 and L2 are defined as on figure 15 / page 20 from the "Optical simulation of the SunCycle concentrator using Scientrace (J. Bos-Coenraad 2013)
            Vector L1 = incoming_trace_direction - incoming_normal_projection;
            double L2 = (oldrefindex / newrefindex) * L1.length;

            // If L2 is larger than 1, full internal reflection takes place.
            return(L2 > 1);
        }
Example #9
0
		/// <summary>
		/// A trace may have its polarisation components with their relative amplitudes, but
		/// interaction with a surface is likely to decompose these vectors into two new vectors (s and p).
		/// This method will perform this decomposition for vec1 and vec2 into "amp_is" and "amp_ip".
		/// </summary>
		public void calcIncomingAmplitudes() {
			UnitVector s = this.dir_s;
			UnitVector p = this.dir_ip;
			Vector v1 = this.trace_in.getPolarisationVec1();
			Vector v2 = this.trace_in.getPolarisationVec2();

			double squared_vec_sum_is = 0;
			double squared_vec_sum_ip = 0; 
			double oldval_is = 0;
			double oldval_ip = 0;	
			foreach (Vector aVec in new List<Vector>{v1, v2}) {
				squared_vec_sum_is += Math.Pow(aVec.dotProduct(s),2);
				squared_vec_sum_ip += Math.Pow(aVec.dotProduct(p),2);
				oldval_is += aVec.dotProduct(s);
				oldval_ip += aVec.dotProduct(p);
				}
			this.amp_is = Math.Pow(squared_vec_sum_is,0.5);
			this.amp_ip = Math.Pow(squared_vec_sum_ip,0.5);
			/*
			double l1 =	v1.length*v1.length + v2.length*v2.length;
			double l2 = this.amp_is*this.amp_is + this.amp_ip * this.amp_ip;
			Console.WriteLine((l1-l2).ToString()+" =("+l1+"/"+l2+")      from v1/v2:"+v1.length.ToString()+"/"+v2.length.ToString()+" becomes: "+this.amp_is+"/"+this.amp_ip+" was:"+oldval_is+"/"+oldval_ip); 
			/* */
			}
Example #10
0
 /// <summary>
 /// Copy constructor
 /// </summary>
 /// <param name="copyVec">source data to be copied</param>
 public UnitVector(UnitVector copyVec) : base(copyVec.x, copyVec.y, copyVec.z)
 {
     this.init_unit();
 }
        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;
        }
Example #12
0
        public void paramInit(
			Scientrace.Location lens_sphere_location, double lens_sphere_radius, 
			double lens_sphere_radians_min, double lens_sphere_radians_max,
			Scientrace.UnitVector orientation_from_sphere_center, bool double_convex_ring)
        {
            this.sphereLoc = lens_sphere_location;
            this.sphereRadius = lens_sphere_radius;
            //Console.WriteLine("Sphere radius: "+sphereRadius);
            this.radiansMin = lens_sphere_radians_min;
            this.radiansMax = lens_sphere_radians_max;
            this.orientation = orientation_from_sphere_center;
            this.doubleConvexRing = double_convex_ring;

            if (lens_sphere_radians_min > 0) {
            this.innerVoid = new InfiniteCylinderBorder(null, null,
                            lens_sphere_location, orientation_from_sphere_center,
                            lens_sphere_radius*Math.Sin(lens_sphere_radians_min)
                            );
            this.innerVoid.enclosesInside = false;
            }

            this.lensSphere = new Sphere(null, null, lens_sphere_location, lens_sphere_radius);
            this.initBottom();
        }
        /* 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);
        }
Example #14
0
 public override VectorTransform getGridTransform(UnitVector griddirection)
 {
     return(this.primaryborder.getGridTransform(griddirection));
 }
Example #15
0
 /// <summary>
 /// Copy constructor
 /// </summary>
 /// <param name="copyVec">source data to be copied</param>
 public UnitVector(UnitVector copyVec)
     : base(copyVec.x, copyVec.y, copyVec.z)
 {
     this.init_unit();
 }
        public Trace trace_in; // set at construction

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Scientrace.DielectricSurfaceInteraction"/> class.
        /// </summary>
        /// <param name="incoming_trace">Incoming trace.</param>
        /// <param name="interaction_loc">Interaction location.</param>
        /// <param name="surface_normal">Surface normal.</param>
        /// <param name="refindex_from">Refractive index for the current volume</param>
        /// <param name="refindex_to">Refractive index on the other side of the surface</param>
        /// <param name="static_absorption_fraction">If absorption at a surface occurs, this fraction is larger than 0.0. A black surface has full=1.0 absorption.</param>
        public DielectricSurfaceInteraction(Trace aTrace, Location interaction_loc, UnitVector	surface_normal, 
											double refindex_from, double refindex_to, Object3d object_to)
        {
            // Store all starting conditions
            this.trace_in = aTrace;
            this.intensity_in = aTrace.intensity;
            this.object_to = object_to;
            this.n_i = refindex_from;
            this.n_t = refindex_to;
            this.dir_i = aTrace.traceline.direction;
            // Make sure the surface normal is oriented in the right direction
            this.surface_normal = surface_normal.orientedAgainst(this.dir_i).tryToUnitVector();
            this.interaction_loc = interaction_loc;

            // Define the "orthogonal to the plane - s" polarisation vector direction
            // Replaced "safeNormalised" method commented out below
            // At normal incidence, you want to retain the polarisation vectors of the trace for the best results
            Scientrace.Vector out_of_plane_vec = this.surface_normal.crossProduct(this.dir_i);
            if (out_of_plane_vec.length < 1E-9)
                out_of_plane_vec = new Vector(this.trace_in.getPolarisationDir1());
            this.dir_s = out_of_plane_vec.tryToUnitVector();
            //this.dir_s = this.surface_normal.safeNormalisedCrossProduct(this.dir_i);

            // Define the "in the plane - p" polarisation vector direction
            this.dir_ip = this.dir_s.crossProduct(this.dir_i).tryToUnitVector();
            this.in_projection = this.dir_i.projectOnPlaneWithNormal(this.surface_normal);

            //First, calculate all properties concerning the incoming trace
            this.applySnellius();
            this.calcIncomingAmplitudes();

            //Before doing anything else, ABSORP the static surface absorption.
            this.subtractStaticAbsorption();

            // If the trace has ended due to total absorption it ends here.
            if (this.total_absorption) return;

            //Now calculate all that other stuff.
            this.calcResultingAmplitudes();
            this.calcResultingIntensities();
            if (Math.Abs(1 - (this.intc_rp + this.intc_tp)) > 1E-9)
                    throw new Exception("p-polarisation fractions don't add op to 1 (rp: "+this.intc_rp+" tp:"+this.intc_tp+")");
            if (Math.Abs(1 - (this.intc_rs + this.intc_ts)) > 1E-9)
                    throw new Exception("s-polarisation fractions don't add op to 1 (rs: "+this.intc_rs+" ts:"+this.intc_ts+")");

            this.calcResultingDirections();

            //this.debugOutput();
        }
 public void calcResultingDirections()
 {
     //Calculate the direction of the reflecting trace:
     UnitVector norm = this.surface_normal.orientedAlong(this.dir_i);
     this.dir_r = this.dir_i.reflectOnSurface(norm);
     this.dir_rp = this.dir_s.crossProduct(this.dir_r).tryToUnitVector();
     Vector l1 = this.in_projection;
     Vector l2 = l1 * (this.n_i / this.n_t);
     // Check for full internal reflection:
     if (l2.length > 1) {
         if (!total_internal_reflection)
             throw new ArgumentOutOfRangeException("Method {calcResultingDirections} finds that full internal reflection occurs, whereas this was not the case for the {applySnellius} method.");
         return;
         }
     this.dir_t = l2.constructHypothenuse(norm);
     this.dir_tp = this.dir_s.crossProduct(this.dir_t).tryToUnitVector();
 }
Example #18
0
 public Vector projectOnDirection(UnitVector aDirection)
 {
     return(aDirection.toVector() * this.dotProduct(aDirection));
 }
Example #19
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
Example #20
0
 public override Scientrace.VectorTransform getGridTransform(UnitVector nz)
 {
     NonzeroVector u, v, w;
     u = this.width;
     v = this.height;
     w = this.length;
     while (Math.Abs(nz.dotProduct(u.normalized())) > 0.99) {
     u = v;
     v = w;
     w = w.vectorDance().tryToUnitVector();
     }
     while (Math.Abs(nz.dotProduct(v.normalized())) > 0.99) {
     v = w;
     w = w.vectorDance().tryToUnitVector();
     }
     /*Console.WriteLine("NEW MAT:"+
                       u.tricon()+
                       v.tricon()+
                       nz.tricon()); */
     return new Scientrace.VectorTransform(u,v,nz);
 }
Example #21
0
 /// <summary>
 /// This method should be overloaded to get a VectorTransformation instance that for
 /// example rotates a grid with the orientation of the object.
 /// </summary>
 /// <param name="nz">
 /// A <see cref="NonzeroVector"/>
 /// </param>
 /// <returns>
 /// A <see cref="Scientrace.VectorTransform"/>
 /// </returns>
 public virtual Scientrace.VectorTransform getGridTransform(UnitVector griddirection)
 {
     Console.WriteLine("getGridTransform not implemented, using static grid for " + this.GetType().ToString() + " instance.");
     return(this.getTransform());
 }
Example #22
0
        /// <summary>
        /// Projects a Vector on a plane with a given normal.
        /// This may also be interpreted as the distance from a vector to its projection on a direction.
        /// </summary>
        /// <returns>The vector component orthogonal to the surface normal.</returns>
        /// <param name="normal">Normal.</param>
        public Vector projectOnPlaneWithNormal(UnitVector normal)
        {
            Vector normal_component = this.projectOnDirection(normal);

            return(this - normal_component);
        }
Example #23
0
        public void addElements()
        {
            /* see sine_rule_applied.svg */
            double alpha;
            double beta, gamma;

            alpha = this.largeAngle;
            gamma = this.relative_angle;
            beta  = Math.PI - (alpha + gamma);

            /* vteethheight is the vector of the triangularprism that points to the top (see vector "h" below)
             *       /\
             *      /  \
             *     /    \
             *    /      \
             *    \      /|
             * l = \  h=/ |
             *      \  /  |
             *       \/___|
             *      w = ^
             * since uvLargeAngle // b... */

            Scientrace.UnitVector v1u          = this.surfacev1.toUnitVector();
            Scientrace.UnitVector v3u          = this.surfacev3.toUnitVector();
            UnitVector            uvLargeAngle = null;

            try {
                uvLargeAngle = (v3u.toVector() * Math.Sin(alpha) +                   //"z" axis
                                v1u.toVector() * Math.Cos(alpha)).tryToUnitVector(); //"x" axis
            } catch (Exception e) {
                throw new ZeroNonzeroVectorException("Large angle for FresnelPrism has a calculated length 0 \n" + e.Message);
            }

            /* the short angle direction vector below is not used. Commented for possibel relevant future use.
             * Scientrace.UnitVector uvShortAngle = (v1u*Math.Sin(this.largeAngle+this.relative_angle) + //"x" axis
             *                                                                       v3u*Math.Cos(this.largeAngle+this.relative_angle)).tryToUnitVector();  //"z" axis */

            double teethwidth = 2 * this.surfacev1.length / Convert.ToDouble(this.teethCount); //2* because v1 represents a radius, not diameter.

            Scientrace.NonzeroVector vteethheight = null;
            try {
                vteethheight = uvLargeAngle * teethwidth * ((Math.Sin(beta)) / (Math.Sin(gamma)));
            } catch (Exception e) {
                throw new ZeroNonzeroVectorException("Teeth height for FresnelPrism has a calculated length 0 \n" + e.Message);
            }

            Scientrace.Location v1base = (this.loc - this.surfacev1.toLocation());

            double vratio = this.surfacev2.length / this.surfacev1.length;

            Scientrace.NonzeroVector vteethwidth = this.surfacev1.toUnitVector() * teethwidth;

            /* Adding teeth to collection, pointing in v3 direction */
            for (int itooth = 0; itooth < this.teethCount; itooth++)
            {
                double distfromcenter = (Math.Abs((0.5 * teethCount) - (itooth + 0.5)) - 0.5) / (0.5 * teethCount);
                //vteethlength is the equiv for vector c in sine_rule_applied.svg and w in ascii scetch above.
                Scientrace.NonzeroVector vteethlength =         //*2 because real length is double the length from the center-line.
                                                        (this.surfacev2 * (Math.Sqrt(1 - Math.Pow(distfromcenter, 2)) * vratio)) * 2;

                //	Console.WriteLine(itooth+" @ "+((this.divisioncount*itooth)/this.teethCount));
                Scientrace.Object3d tri = new Scientrace.TriangularPrism(
                    this.division[(this.divisioncount * itooth) / this.teethCount], this.fresnelMaterial,
                    ((v1base /*+this.surfacev3*/) + (v1u.toVector() * itooth * teethwidth) - (vteethlength * 0.5)).toLocation(),
                    vteethwidth, vteethheight, vteethlength);

                tri.tag = "prismdent_" + itooth;
            }
            /* Adding "top layer, circular prism, on which the teeth are attached. Height surfacev3 */

            /* since the top circularprism was moved, the shift (+this.surfacev3) at the adding of the teeth was
             * also commented out */

            //Scientrace.CircularPrism topcircle = new Scientrace.CircularPrism(this, this.fresnelMaterial, loc, this.surfacev1, this.surfacev2, this.surfacev3);
            //adding to second half, true that's a bit redundant...
            //this.secondhalf.addObject3d(topcircle);

            /* Define the total height of the circle and the teeth in the surfacev3-direction for the environment
             * to request for total size purposes */

            this.total_prism_height =     //this.surfacev3.length + //OBSOLETE SINCE TOP CIRCULARPRISM HAS BEEN REMOVED
                                      Math.Abs(vteethheight.dotProduct(this.surfacev3.toUnitVector()));

            //Setting boundaries for first and second half collections:
            if (this.teethCount < this.divisioncount)
            {
                this.divisioncount = 2;
                Console.WriteLine("Warning: Less teeth(" + this.teethCount + ") for prism than divisions(" + this.divisioncount + "), now setting divisioncount to 2.");
                //throw new ArgumentOutOfRangeException("Less teeth("+this.teethCount+") for prism than divisions("+this.divisioncount+")");
            }
            for (int idiv = 0; idiv < this.divisioncount; idiv++)
            {
                double divstart = Math.Ceiling((double)(idiv * teethCount) / (double)this.divisioncount);
                double divend   = Math.Ceiling((double)((1 + idiv) * teethCount) / (double)this.divisioncount);
                //Math.Ceiling(double((idiv+1)*teethCount) / this.divisioncount);
                //Console.WriteLine("idiv: "+idiv+" divstart:"+divstart+" divend:" +divend + " tc:"+teethCount+" dc:"+divisioncount);
                double divstartfrac = (double)divstart / (double)teethCount;
                double divendfrac   = (double)divend / (double)teethCount;
                this.division[idiv].dummyborder = new RectangularPrism(null, this.materialproperties,
                                                                       loc - surfacev1 - surfacev2 + (surfacev1.toVector() * divstartfrac * 2), //location
                                                                       (surfacev1 * (divendfrac - divstartfrac) * 2),                           //width or length
                                                                       surfacev2 * 2,                                                           //length or width
                                                                       surfacev3.normalized() * this.total_prism_height                         //height
                                                                       );
                //Console.WriteLine("DIV:"+idiv+" has "+this.division[idiv].objects.Count+" children");
            }
        }
Example #24
0
 public override VectorTransform getGridTransform(UnitVector griddirection)
 {
     return this.primaryborder.getGridTransform(griddirection);
 }