public void testDotProductResults() { Random r = new Random(); for (int i = 0; i<1000; i++) { Scientrace.Vector a,b; a = new Scientrace.Vector(r.NextDouble()*100,r.NextDouble()*100,r.NextDouble()*100); b = new Scientrace.Vector(r.NextDouble()*100,r.NextDouble()*100,r.NextDouble()*100); Assert.LessOrEqual(Math.Abs(a.tryToUnitVector().dotProduct(b.tryToUnitVector())), 1); } }
public void testDotProductResults() { Random r = new Random(); for (int i = 0; i < 1000; i++) { Scientrace.Vector a, b; a = new Scientrace.Vector(r.NextDouble() * 100, r.NextDouble() * 100, r.NextDouble() * 100); b = new Scientrace.Vector(r.NextDouble() * 100, r.NextDouble() * 100, r.NextDouble() * 100); Assert.LessOrEqual(Math.Abs(a.tryToUnitVector().dotProduct(b.tryToUnitVector())), 1); } }
public string getX3DRotationTag(Scientrace.NonzeroVector fromVector, Scientrace.NonzeroVector toVector) { Scientrace.Vector r = fromVector.crossProduct(toVector); double angle = Math.Acos(toVector.normalized().dotProduct(fromVector.normalized())) // the angle to be rotated * Math.Sign(r.crossProduct(fromVector).dotProduct(toVector)); try { return("<Transform rotation='" + r.tryToUnitVector().trico() + " " + angle + "' >"); } catch { // if fromVector has the same direction as toVector, the crossProduct is a zerovector which cannot be normalized. return("<Transform>"); //no transformation, just open so it can be closed afterwards } }
public string x3dRotationTransform(Scientrace.Vector orivec) { //the Circle2D objects will normally be drawn in the x,y plane (perpendicular to 0,0,1) so it has to //rotated out of that plane as follows. Scientrace.UnitVector oriunivec = orivec.tryToUnitVector(); Scientrace.UnitVector uxv = (this.u.crossProduct(this.v).tryToUnitVector()); if (uxv == oriunivec) { return("<Transform rotation='0 0 0 0'>"); // throw new ArithmeticException("Plane vectors uxv ("+uxv.trico()+") & oriunivec ("+oriunivec.trico()+") are equal"); } try { Scientrace.UnitVector rotaxis = (oriunivec).crossProduct(uxv).tryToUnitVector(); return("<Transform rotation='" + rotaxis.trico() + " " + (oriunivec.angleWith(rotaxis)).ToString() + "'>"); } catch // possible error: zerovector after cross product (rounding error at first comparison), return zero rotation tag. { return("<Transform rotation='0 0 0 0'>"); } }
public double angleOnSurface(Scientrace.Vector aVector) { return(this.angleOnSurface(aVector.tryToUnitVector())); }
private Scientrace.NonzeroVector calcTriangleHeightVector(ShadowObject3d sho3d) { Scientrace.Vector length = sho3d.getVector("length"); Scientrace.Vector width = sho3d.getVector("width"); Scientrace.Vector heightdir = sho3d.getVector("heightdir"); double angle = sho3d.getDouble("angle"); //create a vector orthogonal to length en width in the same binary direction as heightdir. Scientrace.UnitVector owl = (width.crossProduct(length) * Math.Sign(width.crossProduct(length).dotProduct(heightdir))).tryToUnitVector(); Scientrace.NonzeroVector bdir = ( //calculate the direction of the short side of the prism owl * Math.Sin(angle) + width.tryToUnitVector() * Math.Cos(angle) ).tryToNonzeroVector(); if ((bdir.length < 0.99999) || (bdir.length > 1.00001)) { throw new ArgumentOutOfRangeException("bdir.length", bdir.length, "!= 1"); } Scientrace.VectorTransform trf = new Scientrace.VectorTransform( width.tryToNonzeroVector(), owl.tryToNonzeroVector(), length.tryToNonzeroVector()); Scientrace.NonzeroVector hdirtrf = trf.transform(heightdir).tryToNonzeroVector(); Scientrace.Vector hprimetrf = new Scientrace.Vector(hdirtrf.x, hdirtrf.y, 0); //eliminate "length" component of heightdir in hprime //Console.WriteLine("HPRIMTRF:"+hprimetrf.trico()); Scientrace.NonzeroVector hprimedir = trf.transformback(hprimetrf).tryToNonzeroVector().normalized(); /* ^ * /C\ * / \ * h'/ \ b * / \ * /B_______A\ * width * angle = A; beta = B; gamma = C. */ //sine rule: hprimelen / sin A = width.length() / sin C = blen / sin B double beta, gamma; beta = Math.Acos(hprimedir.normalized().dotProduct(width.tryToNonzeroVector().normalized())); gamma = Math.PI - (angle + beta); double hprimelen; double sinruleconstant = width.length / Math.Sin(gamma); hprimelen = sinruleconstant * Math.Sin(angle); Scientrace.NonzeroVector hprime = hprimedir * hprimelen; // check: (trf.transform(hprime).x / hdirtrf.x) == (trf.transform(hprime).y / hdirtrf.y) double xycoeff = ((trf.transform(hprime).x / hdirtrf.x) / (trf.transform(hprime).y / hdirtrf.y)); if (Math.Abs(1 - xycoeff) > 0.00001) //doesn't do anything if .x/.x = NaN, but that's OK for now. { throw new ArgumentOutOfRangeException("xycoeff", xycoeff, "!=1"); } try { Scientrace.NonzeroVector h = ((Math.Abs(hdirtrf.x) > Math.Abs(hdirtrf.y)) ? // Preventing .x or .y denominator == 0 errors. trf.transformback(hdirtrf * (trf.transform(hprime).x / hdirtrf.x)) : trf.transformback(hdirtrf * (trf.transform(hprime).y / hdirtrf.y)) ).tryToNonzeroVector(); return(h); } catch (Scientrace.ZeroNonzeroVectorException zne) { Console.WriteLine("ERROR: calculated height for triangularprism has length zero!"); throw (zne); } } //end calcTriangleHeightVector
/* Classes supporthing the creation of the lightsource */ public Scientrace.LightSource setRandomCylinderLightFromXData(XElement xlight, Scientrace.Object3dEnvironment env) { //Reading LightSource parameters from XML-element /* "RandomCylinder" * d class.radius, d distance, i beamcount, i maxinteractions, d minintensity * str spectrum, vec location, vec direction */ double radius = this.X.getXDouble(xlight.Attribute("Radius")); if (radius <= 0) { throw new ArgumentOutOfRangeException("Radius " + radius + " out of range"); } double distance = this.X.getXDouble(xlight.Attribute("Distance"), 0); int beamcount = this.X.getXInt(xlight.Attribute("RayCount"), this.X.getXInt(xlight.Attribute("BeamCount"))); //int maxinteractions = this.X.getXInt(xlight.Attribute("MaxInteractions"), 8); //default value max_interactions -> 8 double minintensity = this.X.getXDouble(xlight.Attribute("MinIntensity"), 0.01); //default minimum intensity for tracing set to 1% Scientrace.Vector light_direction = this.X.getXVector(xlight.Element("Direction")); Scientrace.Location centerloc = this.X.getXVector(xlight.Element("Location")).toLocation(); Scientrace.Location locoffset = (light_direction.negative() * distance).toLocation(); //distance cm above surface Scientrace.Location loc = locoffset + centerloc; XMLSpectrumParser xsp = new XMLSpectrumParser(); Scientrace.LightSpectrum spectrum = xsp.parseLightSpectrum(xlight.Element("Spectrum")); Scientrace.LightSource retlight = new Scientrace.RandomCircleLightSource(env, loc, light_direction.tryToUnitVector(), new Scientrace.Plane(new Scientrace.Location(0, 0, 0), new Scientrace.NonzeroVector(1, 0, 0), new Scientrace.NonzeroVector(0, 0, 1)), radius, beamcount, spectrum); //retlight.max_interactions = maxinteractions; retlight.minimum_intensity_fraction = minintensity; return(retlight); }
public double angleWith(Scientrace.Vector v) { return(Math.Acos(this.roundForInverseAngleFunction(this.tryToUnitVector().dotProduct(v.tryToUnitVector())))); }