Проекция вращения CALayer

Слой с frame {0,0,w,h}, backgroundColor red,anchorPoint at {0,0.5}, transform.m34 = -1.0/1800, и установите position at {0,0}, затем поверните его на угол вдоль y , CATransform3DRotate(layer.transform , 0.25 * M_PI, 0, 1, 0), теперь я хочу определить ширину красной области.

Сначала я думал, что это должно быть cos(0.25 * M_PI) *w, затем я тестировал его с помощью кода, красная область короче, чем cos(0.25 * M_PI) *w, это должно быть из-за перспективы (чем ближе объект, тем больше он кажется), но я не знаю, как чтобы определить ширину красной области.


person Luke    schedule 31.05.2012    source источник
comment
Я написал об этом пост, любой, кто может читать по-китайски, просто взгляните на geeklu. com/2012/07/ios-3d-перспектива   -  person Luke    schedule 08.07.2012


Ответы (1)


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

Допустим, ваш якорь находится в начале координат, используя основные матрицы столбцов (например, open GL и CA Layer). Position1 будет представлять левый край вашего прямоугольника, Position2 — правый.

Position1 = {1,0,0,0,
            0,1,0,0,
            0,0,1,0,
            0,0,0,1};

Position2 ={1,0,0,w,  
            0,1,0,0,  
            0,0,1,0,  
            0,0,0,1};  

Позиция 2 теперь должна быть повернута на ваш угол вокруг оси Y, поэтому мы объявляем

Rotation = {cos,0,sin,0,
              0,1,  0,0,
           -sin,0,cos,0,
              0,0,  0,1};

Вращение необходимо применить к Position2, и оба они должны быть умножены на матрицу проекции. Положение 1 не нуждается в вращении, поскольку оно лежит на оси вращения. Важно понимать, что просто установка m34 в небольшое отрицательное число не делает ничего волшебного, что вы действительно делаете, так это умножаете на матрицу проекции.

YourProjection = {1,0,0        ,0,
                  0,1,0        ,0,
                  0,0,1        ,0,
                  0,0,-1.0/1800,1};

Умножение на другой формат проекционной матрицы работает так же хорошо, используйте то, что вам больше всего знакомо. Вы можете использовать матрицу типа Open GL или типа вы используете, потому что они действительно эквивалент.

Position2 = MultiplyMatrices(Rotation,Position2);
Position2 = MultiplyMatrices(YourProjection,Position2);
Position1 = MultiplyMatrices(YourProjection,Position1);

Position1 и Position2 теперь содержат точные позиции, которые им будут даны, когда ваш CALayer выполнит для них преобразование. Поскольку они находятся в однородных координатах, вы должны обязательно разделить свои компоненты x, y, z (m41,42,43) на w (m44), чтобы преобразовать обратно в декартову. Тогда все, что вам нужно сделать, чтобы получить ширину

float width = Position1.m41-Position2.m41;

Если вы еще этого не сделали, вам, вероятно, следует создать функции, выполняющие умножение матриц, чтобы вы могли выполнять такие вычисления быстро и легко. Также таким образом вы не сможете запутаться из-за алгебраических ошибок :). Если вы действительно хотите сделать это алгебраически, просто умножьте это, и это должно дать вам то, что вы ищете. Также на случай, если моя матричная нотация сбивает с толку, вот преобразование из основного столбца в переменные CALayer.

{m11,m12,m13,m14,
 m21,m22,m23,m24,
 m31,m32,m33,m34,
 m41,m42,m43,m44};

где простая матрица перевода будет

{1,0,0,0,
 0,1,0,0,
 0,0,1,0,
 x,y,z,1};
person Hammer    schedule 08.06.2012
comment
Большое спасибо, я проверю ваш ответ завтра. И если нужно, я загружу скриншот проблемы. - person Luke; 08.06.2012
comment
Согласно вашему ответу, теперь я могу определить ширину. Большое спасибо еще раз. - person Luke; 10.06.2012