public void TestFailingRealIntersections()
        {
            Scientrace.Object3dEnvironment env = DummySources.dEnv();
            Scientrace.CylindricalBorder   cb  = new Scientrace.CylindricalBorder(new Scientrace.Location(0, -0.07, 0), new Scientrace.NonzeroVector(0, -0.57, 0), 0.5);
            Scientrace.ParabolicMirror     pm  = new Scientrace.ParabolicMirror(env
                                                                                , Scientrace.PerfectMirror.Instance, new Scientrace.Location(0.354861881099294, -0.57, 0.276718350209505)
                                                                                , new Scientrace.UnitVector(-0.343710964996787, 0.900014703397015, -0.268022958363946), 2, cb);
            Scientrace.Line tl = new Scientrace.Line(-0.184140645666577, -0.0383229578843359, -0.3, 0.343710966184079, -0.900014705907235, 0.268022948412108);

//		pm.trf.transform(tl);
//		Scientrace.IntersectionPoint[] tips = pm.realIntersections(tl);
            //Assert.AreEqual(new Scientrace.Location(0,0,0), tips[0].loc);

            Scientrace.VectorTransform trf     = pm.trf;
            Scientrace.Line            trfline = trf.transform(tl - pm.loc);
            //transform location AND direction
            Scientrace.IntersectionPoint[] ips = pm.baseintersections(trfline);
            //Scientrace.IntersectionPoint tip;
            Scientrace.IntersectionPoint[] retips = new Scientrace.IntersectionPoint[2];
            for (int ipi = 0; ipi < ips.GetLength(0); ipi++)
            {
                if (ips[ipi] == null)
                {
                    retips[ipi] = null;
                    continue;
                }

                //check below removed for performance reasons
                if (!trfline.throughLocation(ips[ipi].loc, 0.00001))
                {
                    string warning = @"ERROR: GOING DOWN! \n baseintersections " + trfline + " FAILED!";
                    throw new ArgumentOutOfRangeException(warning + ips[ipi].loc.trico() + " not in line " + trfline);
                }
            }
        }
Beispiel #2
0
 public Scientrace.UnitVector getNorm()
 {
     //the VectorTransform this.trf object already produced a cross product over this.u and this.v,
     //resulting in normalized (unit-vector) norm on the surface.
     Scientrace.VectorTransform trf = this.getTransform();
     return(trf.w.tryToUnitVector());
 }
Beispiel #3
0
        public Scientrace.Vector lineThroughPlaneTLoc(Scientrace.Line line)
        {
            Scientrace.VectorTransform trf = this.getTransform();
            //coordinates after coordinate-transformation. u->e1, v->e2, loc->eloc
            //the parallelogram is in the (a*e1, b*e2, 0) plane
            Scientrace.Vector eloc;
            eloc = this.geteloc();
            //coordinates after coordinate-transformation. line.direction->eld, line.loc->ell
            Scientrace.Vector eld, ell;
            eld = trf.transform(line.direction);
            ell = trf.transform(line.startingpoint);
            //nbase is the new base when the parallelogram "location" has been substracted from the line-location
            Scientrace.Vector nbase = ell - eloc;

            //catch direction eld.z = 0; line is parallel to plane!
            if (eld.z == 0)
            {
                return(null);
            }

            double nx, ny, nz;
            double dfac = (nbase.z / eld.z);

            nx = nbase.x - (dfac * eld.x);
            ny = nbase.y - (dfac * eld.y);
            nz = nbase.z - (dfac * eld.z);

            //shift plane back to eloc location and return
            return((new Scientrace.Vector(nx, ny, nz)) + eloc);
        }
 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);
 }
Beispiel #5
0
 public override Scientrace.Location get2DLoc(Scientrace.Location loc)
 {
     //Scientrace.VectorTransformOrthonormal trf = new Scientrace.VectorTransformOrthonormal(this.surface.u, this.surface.v);
     //Scientrace.VectorTransform trf = new Scientrace.VectorTransform(this.surface.u, this.surface.v);
     Scientrace.VectorTransform trf = new Scientrace.VectorTransform(this.parallelogram.plane.u.normalized(), this.parallelogram.plane.v.normalized());
     return(trf.transform(loc - this.parallelogram.plane.loc));
 }
 public virtual VectorTransform getTransform()
 {
     //construction on request
     if (this.trf == null)
     {
         this.trf = this.createNewTransform();
     }
     return(this.trf);
 }
Beispiel #7
0
 public Scientrace.VectorTransform getTransform()
 {
     //construction on request
     if (this.trf == null)
     {
         this.trf = new Scientrace.VectorTransform(this.u, this.v);
     }
     return(this.trf);
 }
 public void TransformMatrixTest()
 {
     Scientrace.NonzeroVector u, v;
     u = new Scientrace.NonzeroVector(2, 3, 4);
     v = new Scientrace.NonzeroVector(1, 2, 3);
     Scientrace.VectorTransform foo  = new Scientrace.VectorTransform(u, v);
     Scientrace.Vector          tvec = foo.transform(new Scientrace.Vector(1, 1.5, 2));
     Assert.AreEqual(tvec.x, 0.5);
     Assert.AreEqual(tvec.y, 0, 1E-15);
     Assert.AreEqual(tvec.z, 0, 1E-15);
 }
 public void TransformMatrixAndBackToStringTest()
 {
     Scientrace.NonzeroVector u, v;
     u = new Scientrace.NonzeroVector(5, 2, 4);
     v = new Scientrace.NonzeroVector(3, 2, 3);
     Scientrace.VectorTransform foo      = new Scientrace.VectorTransform(u, v);
     Scientrace.Vector          orivec   = new Scientrace.Vector(5, 1, 2);
     Scientrace.Vector          tvec     = foo.transform(orivec);
     Scientrace.Vector          tbackvec = foo.transformback(tvec);
     Assert.AreEqual(orivec.ToCompactString(), tbackvec.ToCompactString());
 }
 public void CreateOrtho3rdVector()
 {
     Scientrace.UnitVector u, v;
     u = new Scientrace.UnitVector(2, 3, 4);
     v = new Scientrace.UnitVector(1, 2, 3);
     Scientrace.VectorTransform foo = new Scientrace.VectorTransform(u, v);
     Assert.AreNotEqual(0, u.dotProduct(v));
     //, 1E-15);
     Assert.AreEqual(0, u.dotProduct(foo.w), 1E-15);
     Assert.AreEqual(0, v.dotProduct(foo.w), 1E-15);
 }
 public void TransformMatrixAndBackTest2()
 {
     Scientrace.NonzeroVector u, v;
     u = new Scientrace.NonzeroVector(2.3, 3.2, 4.23);
     v = new Scientrace.NonzeroVector(3.14, 2.12, 3);
     Scientrace.VectorTransform foo      = new Scientrace.VectorTransform(u, v);
     Scientrace.Vector          tvec     = foo.transform(new Scientrace.Vector(6, 3, 8));
     Scientrace.Vector          tbackvec = foo.transformback(tvec);
     Assert.AreEqual(tbackvec.x, 6, 1E-14);
     Assert.AreEqual(tbackvec.y, 3, 1E-14);
     Assert.AreEqual(tbackvec.z, 8, 1E-14);
 }
        public void PGramIntersectionAtBaseVectors2()
        {
            Scientrace.Location        loc           = new Scientrace.Location(1, 2, 3);
            Scientrace.NonzeroVector   v1            = new Scientrace.NonzeroVector(2, 5, 7);
            Scientrace.NonzeroVector   v2            = new Scientrace.NonzeroVector(3, 2, 0);
            Scientrace.Parallelogram   pg            = new Scientrace.Parallelogram(loc, v1, v2);
            Scientrace.Vector          intersection  = pg.plane.lineThroughPlane(new Scientrace.Line(1, 1, -1, 2, 2, 2));
            Scientrace.VectorTransform trf           = pg.plane.getTransform();
            Scientrace.Vector          tintersection = trf.transform(intersection - loc);

            /* when the pgram-plane is shifted through 0,0,0, a transformation of any location in this plane to
             * the base vectors e1 and e2 (based on v1 and v2) should leave a 3rd coordinate set to zero. */
            Assert.AreEqual(tintersection.z, 0, 1E-14);
        }
Beispiel #13
0
 public override bool contains(Location tryloc)
 {
     Scientrace.VectorTransform trf        = this.getTransform();
     Scientrace.Vector          trfdtryloc = trf.transform(tryloc - this.loc);
     if (!this.valuewithin(trfdtryloc.x, 0, 1))
     {
         return(false);
     }
     if (!this.valuewithin(trfdtryloc.y, 0, 1))
     {
         return(false);
     }
     if (!this.valuewithin(trfdtryloc.z, 0, 1))
     {
         return(false);
     }
     return(true);
 }
        public override bool contains(Location aLocation)
        {
            Scientrace.VectorTransform trf = this.getTransform();
            Scientrace.Location        tloc = trf.transform(aLocation - this.loc);
            double ufac, vfac;

            // ufac is the fraction of "a vector 1,0,0 transformedback.length" of the radius of the cylinder
            ufac = Vector.x1trbl(trf) / this.radius;
            vfac = Vector.y1trbl(trf) / this.radius;
            //checking for exceptions
            if ((tloc.z < 0) || (tloc.z > 1))
            {
                return(false);        //location lies below or above cylinder != within
            }
            if (Math.Pow(tloc.x * ufac, 2) + Math.Pow(tloc.y * vfac, 2) > 1)
            {
                return(false);        //location lies outside the cylinder
            }
            return(true);
        }
Beispiel #15
0
 /// <summary>
 /// If a vector 1,0,0 would be transformed back by vectortransform trf this would be its length
 /// </summary>
 /// <param name="trf">
 /// A <see cref="Scientrace.VectorTransform"/>
 /// </param>
 /// <returns>
 /// A <see cref="System.Double"/> the length of the backtransform of 1,0,0
 /// </returns>
 public static double x1trbl(Scientrace.VectorTransform trf)
 {
     return(trf.transformback(Scientrace.Vector.x1vector()).length);
 }
Beispiel #16
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;
 }
        public override string exportX3D(Scientrace.Object3dEnvironment env)
        {
            int steps = this.exportX3Dgridsteps;

            Scientrace.AbstractGridBorder cborder = this.cborder;
//		Scientrace.VectorTransform cbordertrf = cborder.getTransform();
            //Generate a rotating grid!
            Scientrace.VectorTransform cbordertrf = cborder.getGridTransform(this.zaxis);
            //Console.WriteLine("CBTRFcp: "+cbordertrf.ToCompactString());

            /*
             * stloc: starting location actually representing the center of the border,
             * from there in the orthonormal direction of this border the collision points with
             * the parabolic mirror will be found (from -radius to +radius in both transform-directions
             */
            Scientrace.Location            stloc = cborder.getOrthoStartCenterLoc();// - cborder.getOthoDirection();
            Scientrace.IntersectionPoint[] iparr, iparre, iparrs;
            Scientrace.Intersection        cintr, eintr, sintr;

            /*
             * eloc is the location "east" of the current node, sloc "south" for drawing a grid
             * of course are terms east and south symbolic
             */
            Scientrace.Location eloc, sloc;
            Scientrace.Line     cline, eline, sline;
            //double r = cborder.getRadius();
            double r1 = cborder.getURadius();
            double r2 = cborder.getVRadius();

            Scientrace.Vector v1     = cbordertrf.u.tryToUnitVector().toVector();
            Scientrace.Vector v2     = cbordertrf.v.tryToUnitVector().toVector();;
            string            retstr = "";

            Scientrace.X3DGridPoint concentrationpoint = new Scientrace.X3DGridPoint(env, this.getConcentrationPoint(), null, null);
            retstr  = concentrationpoint.x3DSphere(env.radius / 1000, "1 0 1", 0.5);
            retstr += concentrationpoint.x3DLineTo(this.loc, "1 0 1 1");
            for (double ix = 0.5; ix < steps; ix++)
            {
                for (double iy = 0.5; iy <= steps; iy++)
                {
                    /* Drawing a grid of lines in direction "border.orthodirection" to ParabolicMirror,
                     * at every intersection a gridpoint is located. "cline" are those ortho-dir lines */
                    cline = new Scientrace.Line(((stloc - (v1 * r1) - (v2 * r2)) + (v1 * (r1 * 2 * (ix / steps))) + (v2 * (r2 * 2 * (iy / steps)))).toLocation(),
                                                cborder.getOrthoDirection());
//											cborder.directionlength.toUnitVector());

                    /* USE THE "checkborder = false" function below to always
                     * show the grid-points, also outside borders
                     * iparr is the IntersectionPoint at the Parabolic Mirror for the current ix/iy iteration */
                    iparr = this.realIntersections(cline, true);

/* DEBUG INFO	foreach (IntersectionPoint ip in iparr) {
 *                                      if (ip!=null) {
 *                                              Console.WriteLine("IP AT: "+ip.ToString());
 *                                              } else {
 *                                              Console.WriteLine("NO IP FROM: "+((stloc-(v1*r)-(v2*r))+(v1*(r*2*(ix/steps)))+(v2*(r*2*(iy/steps))))
 +" AND "+cborder.getOrthoDirection());
 *                                              }
 *                                      }*/
                    eline = new Scientrace.Line(((stloc - (v1 * r1) - (v2 * r2)) + (v1 * (r1 * 2 * ((ix + 1) / steps))) + (v2 * (r2 * 2 * (iy / steps)))).toLocation(),
                                                cborder.getOrthoDirection());
//											cborder.directionlength.toUnitVector());
                    iparre = this.realIntersections(eline, true);
                    //defining "east" neighbour
                    eintr = new Intersection(eline, iparre, this);
                    if (eintr.intersects)
                    {
                        eloc = eintr.enter.loc;
                    }
                    else
                    {
                        eloc = null;
                    }
                    sline = new Scientrace.Line(((stloc - (v1 * r1) - (v2 * r2)) + (v1 * (r1 * 2 * ((ix) / steps))) + (v2 * (r2 * 2 * ((iy + 1) / steps)))).toLocation(),
                                                cborder.getOrthoDirection());
//											cborder.directionlength.toUnitVector());
                    iparrs = this.realIntersections(sline, true);
                    //defining "south" neighbour
                    sintr = new Intersection(sline, iparrs, this);
                    if (sintr.intersects)
                    {
                        sloc = sintr.enter.loc;
                    }
                    else
                    {
                        sloc = null;
                    }

                    /* "central" point
                     * where does line "cline" with intersections "iparr" intersect this object?
                     */
                    cintr = new Intersection(cline, iparr, this, true);
                    if (cintr.intersects)               //add existing gridpoints
                    {
                        if (this.x3dgridspheres)
                        {
                            retstr = retstr + new X3DGridPoint(env, cintr.enter.loc, eloc, sloc).exportX3D();
                        }
                        else
                        {
                            retstr = retstr + new X3DGridPoint(env, cintr.enter.loc, eloc, sloc).exportX3DnosphereRGBA("0 0 1 1");
                        }
                    }
                }
            }
            //Console.WriteLine("!!!"+retstr);
            return(retstr + cborder.exportX3D(env));
        }
        public Scientrace.IntersectionPoint[] realIntersections(Scientrace.Line traceline, bool checkBorder)
        {
//			Scientrace.Line line = traceline-this.loc;	//substract loc value from traceline location,
            //leave direction unchanged
            //Console.WriteLine("In untransformed world: traceline -> "+traceline.ToString());
            //default value should be checkBorder = true;
            Scientrace.VectorTransform trf     = this.trf;
            Scientrace.Line            trfline = trf.transform(traceline - this.loc);
            //transform location AND direction
            Scientrace.IntersectionPoint[] ips = this.baseintersections(trfline);
            Scientrace.IntersectionPoint   tip;
            Scientrace.IntersectionPoint[] retips = new Scientrace.IntersectionPoint[2];
            for (int ipi = 0; ipi < ips.GetLength(0); ipi++)
            {
                if (ips[ipi] == null)
                {
                    retips[ipi] = null;
                    continue;
                }
                //Console.WriteLine("$$$$$$$$$$$$$$$$$"+ips[ipi].loc+"in?:"+trfline);
                //Console.WriteLine("___1");

                //check below removed for performance reasons

                /*if (!trfline.throughLocation(ips[ipi].loc, 0.00001)) {
                 *      string warning =@"ERROR: GOING DOWN! \n baseintersections "+trfline+" FAILED!";
                 *      throw new ArgumentOutOfRangeException(warning+ips[ipi].loc.trico() + " not in line " + trfline);
                 * } *///This was removed at 20160222

                /* else {
                 *      Scientrace.Line reflline = trfline.reflectAt(this.baseIntersectionPlane(ips[ipi].loc.x, ips[ipi].loc.y),0);
                 * //Console.WriteLine("___2");
                 *      /*if (!reflline.throughLocation(this.getBaseConcentrationPoint(), 0.000001)) {
                 *              //throw new ArgumentOutOfRangeException("CONCENTREER EENS!");
                 *              }*/
                //	} end of removed check
                //throw new AccessViolationException("FOO");
                //Console.WriteLine("ips["+ipi.ToString()+"]:"+ips[ipi].ToString());

                //tip = trf.transformback(ips[ipi])+this.loc;

                tip                 = ips[ipi].copy();
                tip.loc             = trf.transformback(ips[ipi].loc) + this.loc;
                tip.flatshape.plane = trf.transformback(tip.flatshape.plane);

                //Console.WriteLine("___3");

                /*if (!traceline.throughLocation(tip.loc, 0.0001)) {
                 *      throw new ArgumentOutOfRangeException(tip.loc.trico() + " (transformed) not in line " + traceline);
                 * } else {
                 *      }*/

                if (this.cborder.contains(tip.loc) || !checkBorder)          //is this location within the borders between which the
                //parabolic mirror exists?
                {
                    retips[ipi] = tip;

/*					//below for debug purposes only
 *                                      retips[ipi] = new IntersectionPoint(traceline.startingpoint+
 *                                                                          traceline.direction.toLocation()*(traceline.direction.dotProduct(tip.loc-traceline.startingpoint))
 *                                                                                                            , tip.plane);*/
                }
                else
                {
                    //Console.WriteLine(tip.loc.ToString() + " is NOT within the cborder range-> "+this.cborder);
                    retips[ipi] = null;
                    continue;
                }

                //Console.WriteLine("trf: "+trf.ToString());
                //Console.WriteLine("retips["+ipi.ToString()+"]:"+retips[ipi].ToString());
            }
            return(retips);
        }
 public virtual VectorTransform getTransform()
 {
     //construction on request
     if (this.trf == null) {
     this.trf = this.createNewTransform();
     }
     return this.trf;
 }
Beispiel #20
0
        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
        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);
            }
        }
Beispiel #22
0
 public Scientrace.VectorTransform getTransform()
 {
     //construction on request
     if (this.trf == null) {
     this.trf = new Scientrace.VectorTransform(this.u, this.v);
     }
     return this.trf;
 }