} //end calcTriangleHeightVector public Scientrace.Object3d constructTriangularPrism(XElement xel) { /* Example: * <Prism> * <Location xyz="10;-50;10" /> * <Length xyz="0;100;0" /> * <Width xyz="10;0;0" /> * <Height xyz="5;0;5" /> * <Material Class="NFormula" Formula="1.5+(nm*0.01)" /> * </Prism> */ if (!xel.Name.ToString().IsIn("TriangularPrism", "Prism")) // != "TriangularPrism") { { throw new XMLException("TriangularPrism does not match its name: " + xel.Name.ToString()); } ShadowScientrace.ShadowObject3d shadowO3D = new ShadowScientrace.ShadowObject3d(typeof(Scientrace.TriangularPrism), this.parentcollection, //ClassName this.getXMaterial(xel)); // Base parameters: shadowO3D.arguments.Add("corner_location", this.X.getXLocation(xel, "Location", null)); shadowO3D.arguments.Add("perfect_top", this.X.getXBool(xel, "PerfectFront", true)); shadowO3D.arguments.Add("length", this.X.getXNzVectorByName(xel, "Length")); shadowO3D.arguments.Add("width", this.X.getXNzVectorByName(xel, "Width")); // Optional parameters // TRY: shadowO3D.arguments.Add("height", this.X.getXNzVectorByName(xel, "Height", null)); // ELSE: if (!shadowO3D.hasArgument("height")) { shadowO3D.arguments.Add("heightdir", this.X.getXNzVectorByName(xel, "HeightDirection")); shadowO3D.arguments.Add("angle", this.X.getXAngleByName(xel, "Angle")); shadowO3D.arguments.Add("height", this.calcTriangleHeightVector(shadowO3D)); } //if (! //just throw a warning if prism has no volume. this.triangularPrismHasVolume(shadowO3D); // ) throw new XMLException("Prism has no volume..."); Scientrace.TriangularPrism tretprism = new Scientrace.TriangularPrism(shadowO3D); return(tretprism); }
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 Scientrace.Object3d constructTriangularPrism(XElement xel) { /* Example: <Prism> <Location xyz="10;-50;10" /> <Length xyz="0;100;0" /> <Width xyz="10;0;0" /> <Height xyz="5;0;5" /> <Material Class="NFormula" Formula="1.5+(nm*0.01)" /> </Prism> */ if (!xel.Name.ToString().IsIn("TriangularPrism", "Prism")) { // != "TriangularPrism") { throw new XMLException("TriangularPrism does not match its name: "+xel.Name.ToString()); } ShadowScientrace.ShadowObject3d shadowO3D = new ShadowScientrace.ShadowObject3d(typeof(Scientrace.TriangularPrism), this.parentcollection, //ClassName this.getXMaterial(xel)); // Base parameters: shadowO3D.arguments.Add("corner_location", this.X.getXLocation(xel, "Location", null)); shadowO3D.arguments.Add("perfect_top", this.X.getXBool(xel, "PerfectFront", true)); shadowO3D.arguments.Add("length", this.X.getXNzVectorByName(xel, "Length")); shadowO3D.arguments.Add("width", this.X.getXNzVectorByName(xel, "Width")); // Optional parameters // TRY: shadowO3D.arguments.Add("height", this.X.getXNzVectorByName(xel, "Height", null)); // ELSE: if (!shadowO3D.hasArgument("height")) { shadowO3D.arguments.Add("heightdir", this.X.getXNzVectorByName(xel, "HeightDirection")); shadowO3D.arguments.Add("angle", this.X.getXAngleByName(xel, "Angle")); shadowO3D.arguments.Add("height", this.calcTriangleHeightVector(shadowO3D)); } //if (! //just throw a warning if prism has no volume. this.triangularPrismHasVolume(shadowO3D); // ) throw new XMLException("Prism has no volume..."); Scientrace.TriangularPrism tretprism = new Scientrace.TriangularPrism(shadowO3D); return tretprism; }