Soru Android: Matrix -> preconcat ve postconcat arasındaki fark nedir?


kullanıyorum Matris Bitmapleri ölçeklemek ve döndürmek için Şimdi preconcat & postconcat arasındaki farkın ne olduğunu veya daha kesin olarak aşağıdaki farkın ne olduğunu merak ediyorum:

Şimdiye kadar belirleyebildiğim kadarıyla setRotate her zaman tüm matrisin üzerine yazılırken, PreRotate ve postRotate ile bir matrise birden fazla değişiklik uygulayabilirim (örn. Ölçekleme + döndürme). Ancak, postRotate veya preRotate kullanarak bunları kullandığım durumlar için farklı sonuçlar vermedi.


44
2017-10-04 13:18


Menşei




Cevaplar:


Sorunuza verilen cevap, Android'e özgü değil; Bu bir grafik ve matematik sorusu. Bu cevapta birçok teori var - uyardınız! Sorunuza yüzeysel bir cevap için, aşağıya atlayın. Ayrıca, bu uzun soluklu bir tirad olduğu için, bir yazım hatası ya da iki şeyleri netleştiremem olabilir. Bu durumda özür dilerim.

Bilgisayar grafiğinde, pikselleri (veya 3D, vertices) vektörler olarak temsil edebiliriz. Ekranınız 640x480 ise, ekranınızın ortasındaki nokta için bir 2B vektör (shoddy işaretlemeni affet):

[320]
[240]
[  1]

1'in neden daha sonra önemli olduğunu açıklayacağım. Dönüşümler sıklıkla kullanılarak temsil edilir matrisler çünkü bahsettiğiniz gibi onları bir araya getirmek çok basit (ve çok verimli). Yukarıdaki noktayı 1,5 katına kadar ölçeklendirmek için Sol çarpın Aşağıdaki matris tarafından:

[1.5   0   0]
[  0 1.5   0]
[  0   0   1]

Bu yeni noktayı alacaksın:

[480]
[360]
[  1]

Hangi orijinal noktayı temsil eder, ekranın köşesine göre 1,5 oranında ölçeklendirilir (0, 0). Bu önemlidir: Ölçeklendirme daima köken açısından yapılır. Merkeziniz olarak başka bir nokta ile ölçeklemek istiyorsanız (örneğin, bir sprite ortası gibi), skalanın çeviriye ve orijinale çevirisini “sarmalısın”. Orijinal noktamızın kökeni çevirmek için kullanılan matris:

[1  0  -320]
[0  1  -240]
[0  0     1]

Hangi verim:

[320*1 + 1*-320]   [0]
[240*1 + 1*-240] = [0]
[     1*1      ]   [1]

Yukarıdakileri Kimlik üst sağ köşeye yerleştirilmiş yer değiştirme koordinatları ile matris. İşte bu yüzden 1 ("homojen koordinat") gereklidir: bu koordinatlara yer açmak, böylece çoğaltma kullanarak çeviri yapmak mümkündür. Aksi takdirde, insanlar için daha sezgisel olan, ancak grafik kartlarını halihazırda olduğundan daha karmaşık hale getirecek olan matris ilavesiyle temsil edilmesi gerekir.

Şimdi, matris çarpımı genellikle değişmezYani, bir dönüşümün "eklenmesi" ( çarpılması matrisiniz) bırakıp çarpmadığınızı veya sağa çarpan olup olmadığını belirtmeniz gerekir. Yaptığı fark, dönüştürmelerinizin hangi sıraya göre zincirlendiğini sormaktır. Matrisinizi sağa çarparak preRotate()) rotasyon adımının gerçekleşmesi gerektiğini belirtirsiniz önce az önce istediğin tüm diğer dönüşümler. İstediğiniz bu olabilir, ama genellikle değil.

Çoğu zaman, önemli değil. Eğer sadece bir dönüşüme sahipseniz, örneğin, hiçbir zaman önemli değil :) Bazen, dönüşümleriniz ölçekleme ve döndürme gibi aynı etkiyle her iki sırada da gerçekleşebilir - benim doğrusal cebir paslı, ama bu durumda matris çarpımı aslında değişkendir çünkü ölçek matrisi simetrikYani, kendisini köşegen boyunca yansıtır. Ama gerçekten, sadece bir düşünün: Eğer bir resmi saat yönünde 10 derece döndürürsem ve sonra% 200'e kadar ölçeklendirirsem, önce onu ölçeklendirir, sonra döndürürüm gibi görünür.

Bazı tuhaf bileşik dönüşümleri yapıyor olsaydınız, bir çelişki fark etmeye başlardınız. Benim tavsiyem, postRotate().


123
2018-02-25 23:15



Dokümanlara göre, M.preConcat (diğer)> M '= M * diğer, M.postConcat (diğer)> M' = diğer * M, Şu anda bunun bir kısmını deniyorum ama 'pre' olarak görünüyor. Yapmış olduğunuzdan sonra yeni işlem ve 'post' daha önce yapar. Tercüme ettikten sonra ölçeklendiriyorum, çeviri ve ölçeklendirme gerekiyor çünkü çeviri ölçeklenmiş koordinatlarda. Eğer 'ön'üm' ama 'gönderirim' değilse çalışır. Bu gösterim benim için kafa karıştırıcı, eğer yanılıyorsam haberim olsun. - Kratz
Dokümanları da iki katına çıkarmalıydım. Adlandırma şeması oldukça kafa karıştırıcı, bu yüzden geri aldım. anladığımdan emin değilim sizin notasyon, yine de :) other*M bir sol çarpıdır ve vermelidir Mtarafından takip edilen dönüşümler otherVar. Bence. - Cheezmeister
Bu gösterimi buradan aldım: developer.android.com/reference/android/graphics/... Ayrıca kafa karıştırıcı ismini de buluyorum. - Kratz
özlü ve derinlemesine açıklamalar seviyorum! +1. - rupps
@Cheezmeister, bilgisayar grafikleri hakkında daha fazla bulabileceğim, kaynağınız gibi derinlemesine açıklayabileceğiniz bir kaynak önerebilir misiniz? - DeltaCap


Dün soruyu cevapladım ama bugün yanlış bir şey hissediyorum, cevabını burada düzelttim:

matrix:  float[] values ={1.2f,0.5f,30,0.5f,1.2f,30,0,0,1};

//as we all know, the basic value in matrix,means no transformation added
matrix2:  float[] values2 ={1f,0,0,0,1f,0,0,0,1};

Let's say our matrix values are the values above.

1 、 aşağıdaki gibi dönüşüm yaptığımızda:

matrix.preTranslate(-50, -50);

is equals to do sequence transformation to matrix2 above like below:

matrix2.postTranslate(-50, -50);
matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);// note here
matrix2.postScale(1.2f, 1.2f);
matrix2.postTranslate(30, 30);

Aşağıdaki gibi dönüşümü yaptığımızda 2 、:

matrix.preRotate(50);

is equals to do sequence transformation to matrix2 like below:

matrix2.postRotate(50);
matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);
matrix2.postScale(1.2f, 1.2f);
matrix2.postTranslate(30, 30);

3 、 aşağıdaki gibi dönüşüm yaptığımızda:

matrix.preScale(1.3f,1.3f);

is equals to do sequence transformation to matrix2 like below:

matrix2.postScale(1.3f,1.3f);
matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);
matrix2.postScale(1.2f, 1.2f);
matrix2.postTranslate(30, 30);

Aşağıdaki gibi dönüşümü yaptığımızda 4 、:

 matrix.preSkew(0.4f,0.4f);

aşağıdaki gibi matris2'ye dizi dönüşümü yapmak için eşittir:

 matrix2.postSkew(0.4f,0.4f);
 matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);
 matrix2.postScale(1.2f, 1.2f);
 matrix2.postTranslate(30, 30);

4
2017-09-18 03:34