public Scientrace.Location constructPlaneNodeLoc(Scientrace.Location planeCenter, double radius, double angle, Scientrace.NonzeroVector baseVec1, Scientrace.NonzeroVector baseVec2) { Scientrace.Vector ix = baseVec1.toVector() * radius * Math.Sin(angle); Scientrace.Vector iy = baseVec2.toVector() * radius * Math.Cos(angle); return(planeCenter + ix + iy); }
public Scientrace.SingleRaySource setSingleRayFromXData(XElement xlight, List <Scientrace.UniformTraceModifier> utms, Scientrace.Object3dEnvironment env) { double distance = this.X.getXDouble(xlight.Attribute("Distance"), 0); int beamcount = this.X.getXInt(xlight.Attribute("RayCount"), this.X.getXInt(xlight.Attribute("BeamCount"), 1)); double minintensity = this.X.getXDouble(xlight, "MinIntensity", 0.01); //default minimum intensity for tracing set to 1% Scientrace.NonzeroVector light_direction = this.X.getXNzVector(xlight.Element("Direction")); Scientrace.Location centerloc = this.X.getXVector(xlight.Element("Location")).toLocation(); Scientrace.Location locoffset = (light_direction.toVector().negative() * distance).toLocation(); //distance cm above surface Scientrace.Location loc = locoffset + centerloc; XMLSpectrumParser xsp = new XMLSpectrumParser(); Scientrace.LightSpectrum spectrum = xsp.parseLightSpectrum(xlight.Element("Spectrum")); if (spectrum == null) { throw new Exception("LightSpectrum " + xlight.Element("Spectrum").ToString() + " unknown"); } Scientrace.SingleRaySource retlight = new Scientrace.SingleRaySource(new Scientrace.Line(loc, light_direction.toUnitVector()), beamcount, spectrum, env); retlight.minimum_intensity_fraction = minintensity; retlight.lightsource_modifiers.AddRange(utms); retlight.init(); return(retlight); }
public Vector reflectOnSurface(Scientrace.NonzeroVector norm) { Scientrace.Vector negdir = this.negative(); // Relative mirrorpoint: disregard the location of the line, just the orientations. Scientrace.Vector rel_mirrorpoint = (norm.toVector() * negdir.dotProduct(norm)); //the distance from the surface normal to the direction vector (in the opposite direction) of the incoming line Scientrace.Vector distance_to_normal = (negdir - rel_mirrorpoint); //the direction of the reflected line return(rel_mirrorpoint - distance_to_normal); }
public ParallelSquareLightSource(Scientrace.Object3dEnvironment env, Scientrace.Location cloc, Scientrace.UnitVector direction, Scientrace.NonzeroVector u, Scientrace.NonzeroVector v, int ucount, int vcount, double wavelength) : base(env) { Scientrace.Location loc = (cloc - ((u * (ucount - 1) * 0.5) + (v * (vcount - 1) * 0.5))).toLocation(); for (int iu = 0; iu < ucount; iu++) { for (int iv = 0; iv < vcount; iv++) { //Console.WriteLine("New line at "+(loc+((u.toVector()*iu)+(v.toVector()*iv)).toLocation()).trico()); Scientrace.Line line = new Scientrace.Line(loc + ((u.toVector() * iu) + (v.toVector() * iv)).toLocation(), direction); this.addTrace(new Scientrace.Trace(wavelength, this, line, env, 1, 1)); } } }
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"); } }