Нахождение точек на цилиндре в 3d комнате c # - PullRequest
0 голосов
/ 02 ноября 2019

Пример изображения здесь Я пытаюсь найти способ вычислить точки на верхней поверхности моего цилиндра. Моя ситуация выглядит следующим образом, у меня есть вектор, который определяет направление моих цилиндров в 3d комнате. Тогда я уже вычислил перпендикулярный вектор с помощью

Vector3.Cross(vector1, vector2)

. Теперь я использую диаметр / 2, чтобы вычислить точку, которая лежит на краю круглой верхней поверхности моего цилиндра. Теперь я хочу всегда поворачивать мой вектор на 90 градусов, чтобы получить 4 точки на краю поверхности. Все 4 вектора, определяющие их, должны быть перпендикулярны направлению цилиндров. Можете ли вы помочь мне, как я могу повернуть первый перпендикуляр, чтобы добиться этого?

Я уже пробовал:

Matrix4x4.CreateFromAxisAngle(vectorcylinderdirection, radiant)

Затем я снова вычислил кросс-произведение, но оно не работает, как я хочу.

Редактировать:

        public static void calculatePontsOnCylinder()
    {

        //Calculate Orthogonal Vector to Direction
        Vector3 tCylinderDirection = new Vector3(1, 0, 0);
        Vector3 tOrthogonal = Vector3.Cross(tCylinderDirection, new Vector3(-tCylinderDirection.Z,tCylinderDirection.X,tCylinderDirection.Y));
        Vector3 tNormOrthogonal = Vector3.Normalize(tOrthogonal);

        //Calculate point on surface circle of cylinder
        //10mm radius
        int tRadius = 10;
        Vector3 tPointFinder = tNormOrthogonal * tRadius;

        //tPointFinder add the cylinder start point
        //not yet implemented

        //now i need to rotate the vector always 90 degrees to find the 3 other points on the circular top surface of the cylinder
        //don't know how to do this
        // I thought this should do it
        Matrix4x4.CreateFromAxisAngle(tCylinderDirection, (float)DegreeToRadian(90));



    }

    private static double DegreeToRadian(double angle)
    {
        return Math.PI * angle / 180.0;
    }

На рисунке вы можете увидеть пример, вектор1 - это то, что мне нужно, всегда поворачивается на 90 градусов, а вектор2 будет моим вектором направления цилиндра

Возможно, я нашел правильную формулу:

Vector3 tFinal = Vector3.Multiply((float)Math.Cos(DegreeToRadian(90)), tPointFinder) + Vector3.Multiply((float)Math.Sin(DegreeToRadian(90)), Vector3.Cross(tCylinderDirection, tPointFinder));
        Vector3 tFinal180 = Vector3.Multiply((float)Math.Cos(DegreeToRadian(180)), tPointFinder) + Vector3.Multiply((float)Math.Sin(DegreeToRadian(180)), Vector3.Cross(tCylinderDirection, tPointFinder));
        Vector3 tFinal270= Vector3.Multiply((float)Math.Cos(DegreeToRadian(270)), tPointFinder) + Vector3.Multiply((float)Math.Sin(DegreeToRadian(270)), Vector3.Cross(tCylinderDirection, tPointFinder));

Интересно то, что если я попробую его с (1,1,0) в качестве направления цилиндра, это даст мне правильные направления, но длина будет отличаться для 90 градусов и 270.

1 Ответ

0 голосов
/ 04 ноября 2019

Вот код, который должен решить вашу проблему, предполагая, что входные требования удовлетворены.

        float zCutPlaneLocation = 20; // should not get bigger than cylinder length
        float cylinderRadius = 100;
        Vector3 cylinderCenter = new Vector3(0, 0, 0); // or whatever you got as cylinder center point, given as Vector3 since Point type is not defined

        // will return 360 points on cylinder edge, corresponding to this z section (cut plane),
        // another z section will give another 360 points and so on
        List<Vector3> cylinderRotatedPointsIn3D = new List<Vector3>();

        for (int angleToRotate = 0; angleToRotate < 360; angleToRotate++)
        {
            cylinderRotatedPointsIn3D.Add(GetRotatedPoint(zCutPlaneLocation, angleToRotate, cylinderRadius, cylinderCenter));
        }

         ....

       private static Vector3 GetRotatedPoint(
        float zLocation, double rotationAngleInRadian, float cylinderRadius, Vector3 cylinderCenter)
       {
        Vector2 cylinderCenterInSection = new Vector2(cylinderCenter.X, cylinderCenter.Y);

        float xOfRotatedPoint = cylinderRadius * (float)Math.Cos(rotationAngleInRadian);
        float yOfRotatedPoint = cylinderRadius * (float)Math.Sin(rotationAngleInRadian);

        Vector2 rotatedVector = new Vector2(xOfRotatedPoint, yOfRotatedPoint);
        Vector2 rotatedSectionPointOnCylinder = rotatedVector + cylinderCenterInSection;

        Vector3 rotatedPointOnCylinderIn3D = new Vector3(
                                                    rotatedSectionPointOnCylinder.X,
                                                    rotatedSectionPointOnCylinder.Y,
                                                    zLocation + cylinderCenter.Z);

        return rotatedPointOnCylinderIn3D;
       }

Я только что создал консольное приложение для этого. Первая часть кода должна быть добавлена ​​в основной метод. Работать с этими матрицами не так просто. Также я не уверен, что ваше решение работает нормально для любого вида ракурса. Здесь идея состоит в том, что повернутые точки от цилиндра вычисляются в сечении цилиндра, поэтому в 2D результат перемещается в 3D путем простого добавления z, где Z-сечение было сделано на цилиндре. Я полагаю, что мировая ось и ось цилиндра находятся в одинаковых направлениях. Также, если ваш цилиндр движется (увеличивается) по оси X, а не по оси Z, как в примере, просто включите код Z с помощью X.

Я также прикрепил картинку pictureБольше подробностей. Это должно работать, если у вас есть центр цилиндра, радиус, угол поворота и вы знаете длину цилиндра, так что вы создаете правильные Z-секции на цилиндре. Это может быть сложно для часов / против часовой стрелки, но давайте посмотрим, как это работает для вас.

Если вы хотите справиться с этим с помощью матриц или чего-то еще, я думаю, что в итоге вы получите такой результат. Поэтому я думаю, что вы не можете иметь «все» повернутые точки в одном списке для всей поверхности цилиндра, они будут зависеть от чего-то вроде вращающихся точек сечения Z на цилиндре.

...