/* * 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); }
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; }
/// <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); }
/// <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); /* */ }
/// <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; }
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); }
public override VectorTransform getGridTransform(UnitVector griddirection) { return(this.primaryborder.getGridTransform(griddirection)); }
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(); }
public Vector projectOnDirection(UnitVector aDirection) { return(aDirection.toVector() * this.dotProduct(aDirection)); }
} // 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
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); }
/// <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()); }
/// <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); }
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"); } }
public override VectorTransform getGridTransform(UnitVector griddirection) { return this.primaryborder.getGridTransform(griddirection); }