/* interface IBorder3D implementation */
        /// <summary>
        /// Return true when the specified aLocation is contained by the Sphere. If the
        /// </summary>
        /// <param name='aLocation'>
        /// If set to <c>true</c> a location.
        /// </param>
        public bool contains(Scientrace.Location aLocation)
        {
            VectorTransform trf   = this.getTransform();
            Location        trLoc = trf.transform(aLocation - this.loc);

            return(((trLoc.x * trLoc.x) + (trLoc.y * trLoc.y) <= 1) == this.enclosesInside);
        }
 /// <summary>
 /// The distributionsquare is a measure for the equal-distribution of light over a surface.
 /// An entire surface is split up in quadrants out of which a measure is calculated by averaging
 /// the ratio between all quadrants and each other. Depending on the "order" each quadrant is having
 /// its own ratio calculated as well. For the weight of each order in the total is explained
 /// at the totalDistribution() method.
 /// </summary>
 /// <param name="order">
 /// A <see cref="System.Int32"/> value containing the "currently calculated order". When manually
 /// creating a new DistributionSquare the top order should always be 0. Higher orders are created
 /// internally.
 /// </param>
 /// <param name="max_order">
 /// How many orders should be calculated? A <see cref="System.Int32"/>.
 /// </param>
 /// <param name="loc">
 /// The "top left" location of the surface. A <see cref="Location"/>
 /// </param>
 /// <param name="x">
 /// The direction AND the width of the surface. A <see cref="NonzeroVector"/>
 /// </param>
 /// <param name="y">
 /// The direction AND the height of the surface. A <see cref="NonzeroVector"/>
 /// </param>
 public DistributionSquare(int order, int max_order, Location loc, NonzeroVector x, NonzeroVector y)
 {
     this.order     = order;
     this.max_order = max_order;
     this.x         = x;
     this.y         = y;
     this.loc       = loc;
     if (order < max_order)
     {
         //Console.WriteLine("Smaller "+order+"/"+max_order+", so...");
         this.tl = new DistributionSquare(order + 1, max_order, loc, x * 0.5, y * 0.5);
         this.tr = new DistributionSquare(order + 1, max_order, loc + (x * 0.5).toLocation(), x * 0.5, y * 0.5);
         this.bl = new DistributionSquare(order + 1, max_order, loc + (y * 0.5).toLocation(), x * 0.5, y * 0.5);
         this.br = new DistributionSquare(order + 1, max_order, loc + (x * 0.5 + y * 0.5).toLocation(), x * 0.5, y * 0.5);
     }
     this.trf = new VectorTransform(x, y);
     this.tx  = this.trf.transform(this.x);
     this.ty  = this.trf.transform(this.y);
     this.checkxy();
 }
        /* 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);
        }