コード例 #1
0
        /// <summary>
        /// Checks these 6 atoms to see if they form a trigonal-bipyramidal shape.
        /// </summary>
        /// <param name="atomA">one of the axial atoms</param>
        /// <param name="atomB">the central atom</param>
        /// <param name="atomC">one of the equatorial atoms</param>
        /// <param name="atomD">one of the equatorial atoms</param>
        /// <param name="atomE">one of the equatorial atoms</param>
        /// <param name="atomF">the other axial atom</param>
        /// <returns>true if the geometry is trigonal-bipyramidal</returns>
        public static bool IsTrigonalBipyramidal(IAtom atomA, IAtom atomB, IAtom atomC, IAtom atomD, IAtom atomE, IAtom atomF)
        {
            Vector3 pointA = atomA.Point3D.Value;
            Vector3 pointB = atomB.Point3D.Value;
            Vector3 pointC = atomC.Point3D.Value;
            Vector3 pointD = atomD.Point3D.Value;
            Vector3 pointE = atomE.Point3D.Value;
            Vector3 pointF = atomF.Point3D.Value;

            bool isColinearABF = StereoTool.IsColinear(pointA, pointB, pointF);

            if (isColinearABF)
            {
                // the normal to the equatorial plane
                Vector3 normal = StereoTool.GetNormal(pointC, pointD, pointE);

                // get the side of the plane that axis point A is
                TetrahedralSign handednessCDEA = StereoTool.GetHandedness(normal, pointC, pointF);

                // get the side of the plane that axis point F is
                TetrahedralSign handednessCDEF = StereoTool.GetHandedness(normal, pointC, pointA);

                // in other words, the two axial points (A,F) are on opposite sides
                // of the equatorial plane CDE
                return(handednessCDEA != handednessCDEF);
            }
            else
            {
                return(false);
            }
        }
コード例 #2
0
        public void ColinearTestWithNonColinearPoints()
        {
            Vector3 pointA = new Vector3(1, 1, 1);
            Vector3 pointB = new Vector3(2, 3, 2);
            Vector3 pointC = new Vector3(3, 3, 3);

            Assert.IsFalse(StereoTool.IsColinear(pointA, pointB, pointC));
        }
コード例 #3
0
        private static TetrahedralSign GetHandedness(Vector3 pointA, Vector3 pointB, Vector3 pointC, Vector3 pointD)
        {
            // assumes anti-clockwise for a right-handed system
            Vector3 normal = StereoTool.GetNormal(pointA, pointB, pointC);

            // it doesn't matter which of points {A,B,C} is used
            return(StereoTool.GetHandedness(normal, pointA, pointD));
        }
コード例 #4
0
        public void ColinearTestWithNearlyColinearPoints()
        {
            Vector3 pointA = new Vector3(1, 1, 1);
            Vector3 pointB = new Vector3(2, (float)2.001, 2);
            Vector3 pointC = new Vector3(3, 3, 3);

            Assert.IsTrue(StereoTool.IsColinear(pointA, pointB, pointC));
        }
コード例 #5
0
        public void SquarePlanarTest()
        {
            IAtom atomA = new Atom("C", new Vector3(1, 2, 0));
            IAtom atomB = new Atom("C", new Vector3(1, 1, 0));
            IAtom atomC = new Atom("C", new Vector3(2, 2, 0));
            IAtom atomD = new Atom("C", new Vector3(2, 1, 0));

            Assert.IsTrue(StereoTool.IsSquarePlanar(atomA, atomB, atomC, atomD));
        }
コード例 #6
0
        /// <summary>
        /// Checks the three supplied points to see if they fall on the same line.
        /// It does this by finding the normal to an arbitrary pair of lines between
        /// the points (in fact, A-B and A-C) and checking that its length is 0.
        /// </summary>
        /// <param name="ptA"></param>
        /// <param name="ptB"></param>
        /// <param name="ptC"></param>
        /// <returns>true if the tree points are on a straight line</returns>
        public static bool IsColinear(Vector3 ptA, Vector3 ptB, Vector3 ptC)
        {
            Vector3 vectorAB = new Vector3();
            Vector3 vectorAC = new Vector3();
            Vector3 normal   = new Vector3();

            StereoTool.GetRawNormal(ptA, ptB, ptC, out normal, out vectorAB, out vectorAC);
            return(IsColinear(normal));
        }
コード例 #7
0
        /// <summary>
        /// Gets the tetrahedral handedness of four atoms - three of which form the
        /// 'base' of the tetrahedron, and the other the apex. Note that it assumes
        /// a right-handed coordinate system, and that the points {A,B,C} are in
        /// a counter-clockwise order in the plane they share.
        /// </summary>
        /// <param name="baseAtomA">the first atom in the base of the tetrahedron</param>
        /// <param name="baseAtomB">the second atom in the base of the tetrahedron</param>
        /// <param name="baseAtomC">the third atom in the base of the tetrahedron</param>
        /// <param name="apexAtom">the atom in the point of the tetrahedron</param>
        /// <returns>the sign of the tetrahedron</returns>
        public static TetrahedralSign GetHandedness(IAtom baseAtomA, IAtom baseAtomB, IAtom baseAtomC, IAtom apexAtom)
        {
            Vector3 pointA = baseAtomA.Point3D.Value;
            Vector3 pointB = baseAtomB.Point3D.Value;
            Vector3 pointC = baseAtomC.Point3D.Value;
            Vector3 pointD = apexAtom.Point3D.Value;

            return(StereoTool.GetHandedness(pointA, pointB, pointC, pointD));
        }
コード例 #8
0
        /// <summary>
        /// Given three points (A, B, C), makes the vectors A-B and A-C, and makes
        /// the cross product of these two vectors; this has the effect of making a
        /// third vector at right angles to AB and AC.
        /// </summary>
        /// <remarks>
        /// <note type="note">
        /// The returned normal is normalized; that is, it has been divided by its length.</note></remarks>
        /// <param name="ptA">the 'middle' point</param>
        /// <param name="ptB">one of the end points</param>
        /// <param name="ptC">one of the end points</param>
        /// <returns>the vector at right angles to AB and AC</returns>
        public static Vector3 GetNormal(Vector3 ptA, Vector3 ptB, Vector3 ptC)
        {
            Vector3 vectorAB = new Vector3();
            Vector3 vectorAC = new Vector3();
            Vector3 normal   = new Vector3();

            StereoTool.GetRawNormal(ptA, ptB, ptC, out normal, out vectorAB, out vectorAC);
            Vector3.Normalize(normal);
            return(normal);
        }
コード例 #9
0
        public void GetStereoCWTest()
        {
            IAtom closestAtomToViewer     = new Atom("F", new Vector3(1, 1, 1));
            IAtom highestCIPPriority      = new Atom("I", new Vector3(0, 1, 2));
            IAtom middleCIPPriority       = new Atom("Br", new Vector3(0, 2, 0));
            IAtom nearlylowestCIPPriority = new Atom("Cl", Vector3.Zero);

            Assert.AreEqual(TetrahedralStereo.Clockwise, StereoTool.GetStereo(closestAtomToViewer, highestCIPPriority,
                                                                              middleCIPPriority, nearlylowestCIPPriority));
        }
コード例 #10
0
        public void TrigonalBipyramidalTest()
        {
            IAtom atomA = new Atom("C", new Vector3(1, 1, 2)); // axis point 1
            IAtom atomB = new Atom("C", new Vector3(1, 1, 1)); // center of plane
            IAtom atomC = new Atom("C", new Vector3(0, 1, 1));
            IAtom atomD = new Atom("C", new Vector3(1, 0, 1));
            IAtom atomE = new Atom("C", new Vector3(2, 2, 1));
            IAtom atomF = new Atom("C", new Vector3(1, 1, 0)); // axis point 2

            Assert.IsTrue(StereoTool.IsTrigonalBipyramidal(atomA, atomB, atomC, atomD, atomE, atomF));
        }
コード例 #11
0
        public void GetNormalFromThreePoints()
        {
            // these are, of course, points on these axes, not the axis vectors
            Vector3 axisXPoint = XAXIS;
            Vector3 axisYPoint = YAXIS;

            // the normal of X and Y should be Z
            Vector3 normal = StereoTool.GetNormal(ORIGIN, axisXPoint, axisYPoint);

            Assert.IsTrue(Vector3.Distance(ZAXIS, normal) < 0.0001);
        }
コード例 #12
0
        public void SquarePlanarZShapeTest()
        {
            // all points are in the XY plane
            IAtom atomA = new Atom("C", new Vector3(1, 2, 0));
            IAtom atomB = new Atom("C", new Vector3(1, 1, 0));
            IAtom atomC = new Atom("C", new Vector3(2, 2, 0));
            IAtom atomD = new Atom("C", new Vector3(2, 1, 0));

            SquarePlanarShape shape = StereoTool.GetSquarePlanarShape(atomA, atomB, atomC, atomD);

            Assert.AreEqual(SquarePlanarShape.ZShape, shape);
        }
コード例 #13
0
        public void TetrahedralMinusAtomsBelowXYTest()
        {
            // below the XY plane
            IAtom baseA = new Atom("C", new Vector3(0, 0, -1));
            IAtom baseB = new Atom("C", new Vector3(1, 0, -1));
            IAtom baseC = new Atom("C", new Vector3(1, 1, -1));

            IAtom           negativeApex = new Atom("C", new Vector3(0.5, 0.5, -2));
            TetrahedralSign tetSign      = StereoTool.GetHandedness(baseA, baseB, baseC, negativeApex);

            Assert.AreEqual(TetrahedralSign.Minus, tetSign);
        }
コード例 #14
0
        public void OctahedralTest()
        {
            IAtom atomA = new Atom("C", new Vector3(2, 2, 2)); // axis point 1
            IAtom atomB = new Atom("C", new Vector3(2, 2, 1)); // center of plane
            IAtom atomC = new Atom("C", new Vector3(1, 3, 1));
            IAtom atomD = new Atom("C", new Vector3(3, 3, 1));
            IAtom atomE = new Atom("C", new Vector3(3, 1, 1));
            IAtom atomF = new Atom("C", new Vector3(1, 3, 1));
            IAtom atomG = new Atom("C", new Vector3(2, 2, 0)); // axis point 2

            Assert.IsTrue(StereoTool.IsOctahedral(atomA, atomB, atomC, atomD, atomE, atomF, atomG));
        }
コード例 #15
0
        public void TetrahedralPlusAtomsAboveXYClockwiseTest()
        {
            // above the XY plane
            IAtom baseA = new Atom("C", new Vector3(0, 0, 1));
            IAtom baseB = new Atom("C", new Vector3(1, 0, 1));
            IAtom baseC = new Atom("C", new Vector3(1, 1, 1));

            IAtom           positiveApex = new Atom("C", new Vector3(0.5, 0.5, 2));
            TetrahedralSign tetSign      = StereoTool.GetHandedness(baseC, baseB, baseA, positiveApex);

            Assert.AreEqual(TetrahedralSign.Minus, tetSign);
        }
コード例 #16
0
        public void AllCoplanarTest()
        {
            Vector3 pointA = new Vector3(1, 1, 0);
            Vector3 pointB = new Vector3(2, 1, 0);
            Vector3 pointC = new Vector3(1, 2, 0);
            Vector3 pointD = new Vector3(2, 2, 0);
            Vector3 pointE = new Vector3(3, 2, 0);
            Vector3 pointF = new Vector3(3, 3, 0);

            Vector3 normal = StereoTool.GetNormal(pointA, pointB, pointC);

            Assert.IsTrue(StereoTool.AllCoplanar(normal, pointA, pointB, pointC, pointD, pointE, pointF));
        }
コード例 #17
0
        private static bool IsSquarePlanar(Vector3 pointA, Vector3 pointB, Vector3 pointC, Vector3 pointD, out Vector3 normal)
        {
            // define a plane using ABC, also checking that the are not colinear
            Vector3 vectorAB = new Vector3();
            Vector3 vectorAC = new Vector3();

            GetRawNormal(pointA, pointB, pointC, out normal, out vectorAB, out vectorAC);
            if (StereoTool.IsColinear(normal))
            {
                return(false);
            }

            // check that F is in the same plane as CDE
            return(StereoTool.AllCoplanar(normal, pointC, pointD));
        }
コード例 #18
0
        /// <summary>
        /// Take four atoms, and return <see cref="TetrahedralStereo.Clockwise"/> or <see cref="TetrahedralStereo.AntiClockwise"/>.
        /// The first atom is the one pointing towards the observer.
        /// </summary>
        /// <param name="atom1">the atom pointing towards the observer</param>
        /// <param name="atom2">the second atom (points away)</param>
        /// <param name="atom3">the third atom (points away)</param>
        /// <param name="atom4">the fourth atom (points away)</param>
        /// <returns>clockwise or anticlockwise</returns>
        public static TetrahedralStereo GetStereo(IAtom atom1, IAtom atom2, IAtom atom3, IAtom atom4)
        {
            // a normal is calculated for the base atoms (2, 3, 4) and compared to
            // the first atom. PLUS indicates ACW.
            TetrahedralSign sign = StereoTool.GetHandedness(atom2, atom3, atom4, atom1);

            if (sign == TetrahedralSign.Plus)
            {
                return(TetrahedralStereo.AntiClockwise);
            }
            else
            {
                return(TetrahedralStereo.Clockwise);
            }
        }
コード例 #19
0
        /// <summary>
        /// <para>Given four atoms (assumed to be in the same plane), returns the
        /// arrangement of those atoms in that plane.</para>
        ///
        /// <para>The 'shapes' returned represent arrangements that look a little like
        /// the characters 'U', '4', and 'Z'.</para>
        /// </summary>
        /// <param name="atomA">an atom in the plane</param>
        /// <param name="atomB">an atom in the plane</param>
        /// <param name="atomC">an atom in the plane</param>
        /// <param name="atomD">an atom in the plane</param>
        /// <returns>the shape (U/4/Z)</returns>
        public static SquarePlanarShape GetSquarePlanarShape(IAtom atomA, IAtom atomB, IAtom atomC, IAtom atomD)
        {
            Vector3 pointA = atomA.Point3D.Value;
            Vector3 pointB = atomB.Point3D.Value;
            Vector3 pointC = atomC.Point3D.Value;
            Vector3 pointD = atomD.Point3D.Value;

            // normalA normalB normalC are right-hand normals for the given
            // triangles
            // A-B-C, B-C-D, C-D-A
            Vector3 normalA = new Vector3();
            Vector3 normalB = new Vector3();
            Vector3 normalC = new Vector3();

            // these are temporary vectors that are re-used in the calculations
            Vector3 tmpX = new Vector3();
            Vector3 tmpY = new Vector3();

            // the normals (normalA, normalB, normalC) are calculated
            StereoTool.GetRawNormal(pointA, pointB, pointC, out normalA, out tmpX, out tmpY);
            StereoTool.GetRawNormal(pointB, pointC, pointD, out normalB, out tmpX, out tmpY);
            StereoTool.GetRawNormal(pointC, pointD, pointA, out normalC, out tmpX, out tmpY);

            // normalize the normals
            Vector3.Normalize(normalA);
            Vector3.Normalize(normalB);
            Vector3.Normalize(normalC);

            // sp1 up up up U-shaped
            // sp2 up up Down 4-shaped
            // sp3 up Down Down Z-shaped
            var    aDotB = Vector3.Dot(normalA, normalB);
            double aDotC = Vector3.Dot(normalA, normalC);
            double bDotC = Vector3.Dot(normalB, normalC);

            if (aDotB > 0 && aDotC > 0 && bDotC > 0)
            { // UUU or DDD
                return(SquarePlanarShape.UShape);
            }
            else if (aDotB > 0 && aDotC < 0 && bDotC < 0)
            { // UUD or DDU
                return(SquarePlanarShape.FourShape);
            }
            else
            { // UDD or DUU
                return(SquarePlanarShape.ZShape);
            }
        }
コード例 #20
0
 /// <summary>
 /// Check that all the points in the list are coplanar (in the same plane)
 /// as the plane defined by the planeNormal and the pointInPlane.
 /// </summary>
 /// <param name="planeNormal">the normal to the plane</param>
 /// <param name="pointInPlane">any point know to be in the plane</param>
 /// <param name="points">an array of points to test</param>
 /// <returns>false if any of the points is not in the plane</returns>
 public static bool AllCoplanar(Vector3 planeNormal, Vector3 pointInPlane, params Vector3[] points)
 {
     foreach (var point in points)
     {
         double distance = StereoTool.SignedDistanceToPlane(planeNormal, pointInPlane, point);
         if (distance < PlaneTolerance)
         {
             continue;
         }
         else
         {
             return(false);
         }
     }
     return(true);
 }
コード例 #21
0
        public void NegativePointPlaneDistanceTest()
        {
            // the normal for the Y-Z plane is X
            Vector3 planeNormal = XAXIS;

            Vector3.Normalize(planeNormal);

            // an arbitrary point in the Y-Z plane
            Vector3 pointInPlane = new Vector3(0, 1, 1);

            // make a negative point on the X axis = opposite direction to normal
            Vector3 pointToMeasureNeg = new Vector3(-2, 0, 0);

            double distance = StereoTool.SignedDistanceToPlane(planeNormal, pointInPlane, pointToMeasureNeg);

            Assert.AreEqual(-2.0, distance, 0.1);
        }