コード例 #1
0
        public void Rotate(Chessboard3DReprezentation boardRepresentation, CameraSpacePoint[] csp)
        {
            var firstVector  = boardRepresentation.FieldVector1;
            var secondVector = boardRepresentation.FieldVector2;
            var cornerPoint  = boardRepresentation.CornerOfChessboard;

            firstVector  = MyVector3DStruct.Normalize(firstVector);
            secondVector = MyVector3DStruct.Normalize(secondVector);

            var a    = MyVector3DStruct.CrossProduct(ref firstVector, ref secondVector);
            var b    = MyVector3DStruct.CrossProduct(ref secondVector, ref firstVector);
            var xVec = new MyVector3DStruct();
            var yVec = new MyVector3DStruct();
            var zVec = new MyVector3DStruct();

            // get new base based on two known vectors and their cross product
            if ((a.z > 0 && b.z < 0)) // originally (a.z > 0 && b.z < 0)
            {
                zVec = a;             // a
                yVec = MyVector3DStruct.Normalize(MyVector3DStruct.CrossProduct(ref xVec, ref zVec));
            }
            else if ((a.z < 0 && b.z > 0)) // originally (a.z < 0 && b.z > 0)
            {
                zVec = b;                  // b
                yVec = MyVector3DStruct.Normalize(MyVector3DStruct.CrossProduct(ref xVec, ref zVec));
            }
            else
            {
                throw new InvalidOperationException();
            }

            // normalize base
            xVec = MyVector3DStruct.Normalize(firstVector);
            yVec = MyVector3DStruct.Normalize(secondVector);
            zVec = MyVector3DStruct.Normalize(zVec);

            // get inverse mapping to base
            double[,] matrix =
            {
                { xVec.x, yVec.x, zVec.x },
                { xVec.y, yVec.y, zVec.y },
                { xVec.z, yVec.z, zVec.z }
            };
            var inverseMatrix = matrix.Inverse();

            // move all points
            for (int i = 0; i < csp.Length; i++)
            {
                // translation to corner point
                var nx = (float)(csp[i].X - cornerPoint.x);
                var ny = (float)(csp[i].Y - cornerPoint.y);
                var nz = (float)(csp[i].Z - cornerPoint.z);

                // rotation around it to given base
                csp[i].X = (float)(inverseMatrix[0, 0] * nx + inverseMatrix[0, 1] * ny + inverseMatrix[0, 2] * nz);
                csp[i].Y = (float)(inverseMatrix[1, 0] * nx + inverseMatrix[1, 1] * ny + inverseMatrix[1, 2] * nz);
                csp[i].Z = (float)(inverseMatrix[2, 0] * nx + inverseMatrix[2, 1] * ny + inverseMatrix[2, 2] * nz);
            }
        }
コード例 #2
0
        /// <summary>
        /// Finds most suitable chessboard fitting real points
        /// </summary>
        public static Chessboard3DReprezentation ChessboardFittingAlgorithm(List <Point2D> contractedPoints, ChessboardTrackingCompleteData chessboardData)
        {
            const int takeXNearestNeighbors = 7;

            var contractedPoints3D = ConvertIntersectionsTo3D(contractedPoints, chessboardData);

            var contractedPoints3DasStruct = contractedPoints3D.Select(x => new MyVector3DStruct(x.X, x.Y, x.Z)).ToArray();

            double lowestError = double.MaxValue;
            Chessboard3DReprezentation boardRepresentation = null;

            Parallel.ForEach(contractedPoints3DasStruct, csp =>
            {
                // take _ nearest neighbors
                var neighbors = contractedPoints3DasStruct.OrderBy((MyVector3DStruct x) => MyVector3DStruct.Distance(ref x, ref csp)).Take(takeXNearestNeighbors).ToArray();

                // take all pairs of neighbors
                for (int i = 0; i < neighbors.Length; i++)
                {
                    for (int j = i + 1; j < neighbors.Length; j++)
                    {
                        var first  = neighbors[i];
                        var second = neighbors[j];

                        var firstPoint  = new MyVector3DStruct(first.x, first.y, first.z);
                        var secondPoint = new MyVector3DStruct(second.x, second.y, second.z);

                        // st. point + 2 vectors
                        var initialPoint = new MyVector3DStruct(csp.x, csp.y, csp.z);
                        var firstVector  = MyVector3DStruct.Difference(ref firstPoint, ref initialPoint);
                        var secondVector = MyVector3DStruct.Difference(ref secondPoint, ref initialPoint);

                        // perpendicularity check
                        double angleBetweenVectors = MyVector3DStruct.AngleInDeg(ref firstVector, ref secondVector);
                        if (!(angleBetweenVectors < 91.4 && angleBetweenVectors > 88.6))
                        {
                            break;
                        }

                        // length check
                        double ratio = firstVector.Magnitude() / secondVector.Magnitude();
                        if (!(ratio > 0.85f && ratio < 1.15f))
                        {
                            break;
                        }

                        // ensure right mutual position of first and second vector - otherwise switch them
                        if (MyVector3DStruct.CrossProduct(ref firstVector, ref secondVector).z < 0)
                        {
                            var temp     = firstVector;
                            firstVector  = secondVector;
                            secondVector = temp;
                        }

                        // length normalization of vectors
                        double averageLength = (firstVector.Magnitude() + secondVector.Magnitude()) / 2;

                        firstVector  = MyVector3DStruct.MultiplyByNumber(MyVector3DStruct.Normalize(ref firstVector), averageLength);
                        secondVector = MyVector3DStruct.MultiplyByNumber(MyVector3DStruct.Normalize(ref secondVector), averageLength);

                        var negatedFirstVector  = MyVector3DStruct.Negate(ref firstVector);
                        var negatedSecondVector = MyVector3DStruct.Negate(ref secondVector);

                        // locate all possible starting points
                        for (int f = 0; f < 9; f++)
                        {
                            for (int s = 0; s < 9; s++)
                            {
                                var startingPoint =
                                    MyVector3DStruct.Addition(
                                        MyVector3DStruct.Addition(
                                            MyVector3DStruct.MultiplyByNumber(negatedFirstVector, f),
                                            MyVector3DStruct.MultiplyByNumber(negatedSecondVector, s)
                                            )
                                        , initialPoint
                                        );
                                // generate all possible chessboards for given starting point and compute their error
                                double currentError = 0;

                                for (int ff = 0; ff < 9; ff++)
                                {
                                    for (int ss = 0; ss < 9; ss++)
                                    {
                                        var currentPoint = MyVector3DStruct.Addition(
                                            startingPoint,
                                            MyVector3DStruct.Addition(
                                                MyVector3DStruct.MultiplyByNumber(firstVector, ff),
                                                MyVector3DStruct.MultiplyByNumber(secondVector, ss)
                                                )
                                            );

                                        var closestPointDistance = contractedPoints3DasStruct.Min(x =>
                                                                                                  MyVector3DStruct.Distance(ref currentPoint,
                                                                                                                            new MyVector3DStruct(x.x, x.y, x.z)));

                                        // clipping of max error per point
                                        var clippingDistance = chessboardData.UserParameters.ClippedDistanecInChessboardFittingMetric / 1000f;
                                        closestPointDistance = closestPointDistance > clippingDistance ? clippingDistance : closestPointDistance;

                                        if (chessboardData.UserParameters.IsDistanceMetricInChessboardFittingExperimental)
                                        {
                                            closestPointDistance = closestPointDistance * closestPointDistance;
                                        }

                                        currentError += closestPointDistance;
                                    }
                                }

                                if (currentError < lowestError)
                                {
                                    lowestError         = currentError;
                                    boardRepresentation = new Chessboard3DReprezentation(startingPoint, firstVector, secondVector);
                                }
                            }
                        }
                    }
                }
            });

            return(boardRepresentation);
        }