android.graphics.Matrix类用法分析
本文实例讲述了android.graphics.Matrix类用法。分享给大家供大家参考,具体如下:
Matrix类包含了一个3x3的矩阵用来改变坐标,它没有一个构造器来初始化它里边的内容,所以创建实例后需要调用reset()方法生成一个标准matrix,或者调用set..一类的函数,比如setTranslate,setRotate,,该函数将会决定matrix如何来改变坐标。SDK里边没有讲述Matrix的3x3矩阵是如何改变点的坐标值的,但是我在代码里边通过打印那9个点的值时,大致可以得到如下结论,9个值[a,b,c,d,e,f,g,h,i],坐标[x,y],当g=0,h=0,i=1,的时候,坐标是这样变换的,x'=a*x+b*y+c;y'=d*x+e*y+f;当调用setTranslate(10,20)之后,matrix的值就变成[1,0,10,0,1,20,0,0,1];这其实还是没有脱离矩阵乘法,只是不知道后三位是如何应用的。了解这个对后边的连接矩阵的理解有好处,连接矩阵其实就是两个矩阵相乘后得到的新矩阵。
publicMatrix()
创建一个标准矩阵,应用后点的坐标不会有任何改变
publicMatrix(Matrixsrc)
创建一个src的深度复制,改变规则与src一致
publicbooleanequals(Objectobj)
如果obj为Matrix并且它的值与当前Matrix对象相等的会将会返回true
publicvoidgetValues(float[]values)
获取matrix的那9个值
publicbooleaninvert(Matrixinverse)
将当前矩阵反转,并且反转后的值存入inverse中,如果当前矩阵不能反转,那么inverse不变,返回false,反转规则应该是满足当前矩阵*inverse=标准矩阵,标准矩阵为[1,0,0,0,1,0,0,0,1];不过其实也不用想得那么复杂,比如当前matrix是setTranslate(10,20),那么反转后的matrix就是setTranslate(-10,-20);
publicbooleanisIdentity()
判断当前矩阵是否为标准矩阵,这个函数比if(getType()==0)运行的可能更快一些
publicvoidmapPoints(float[]dst,intdstIndex,float[]src,intsrcIndex,intpointCount)
用当前矩阵改变src中的点的坐标,然后将改变后的值对应的存入dst数组中,其中pointCount表示点的数目,(x,y)=(src[2*k],src[2*k+1])表示一个点的坐标,k取整数值,安卓中用数组存储点的坐标值的时候都是按如此法则存储的。
publicvoidmapPoints(float[]pts)
用当前矩阵改变pts中的值,然后存储在pts中,同上,pts也是存储点的坐标的数组
publicvoidmapPoints(float[]dst,float[]src)
用当前矩阵改变src的值,并且存储到数组dst中
publicfloatmapRadius(floatradius)
将一个半径为radius的圆的所有点坐标用matrix进行变换后,计算出该圆的半径并且返回该值。注意:要得到正确的值该圆默认是有中心的,个人注:说实话不明白这个函数有什么用
publicbooleanmapRect(RectFdst,RectFsrc)
用matrix改变src的4个顶点的坐标,并将改变后的坐标调整后存储到dst中,(RectF只能存储改变后的左上角和右下角坐标,所以需要调整),返回的值跟rectStaysRect()一样,从字面意思可以认为src改变后仍然是RectF,那么就返回true
publicbooleanmapRect(RectFrect)
用matrix改变rect的4个顶点的坐标,并将改变后的坐标调整后存储到rect当中
publicvoidmapVectors(float[]dst,float[]src)
用matrix改变dst中的向量值并且存储到src当中,注意:setTranslate(x,y)这样的matrix调用了这个函数后不会有任何反应,这样的matrix应该调用mapPoints
publicvoidmapVectors(float[]vecs)
用matrix改变vecs中的值并且存储到vecs当中,同上,注意:setTranslate(x,y)这样的matrix调用了这个函数后不会有任何反应,这样的matrix应该调用mapPoints
publicvoidmapVectors(float[]dst,intdstIndex,float[]src,intsrcIndex,intvectorCount)
同上,只不过vectorCount表示向量的数目,dstIndex,srcIndex分别表示各自的起始位置
publicbooleanpostConcat(Matrixother)
将当前的matrix连接到other之后,并且将连接后的值写入当前matrix。M‘=other*M,连接后变换的效果,相当于先变换M,然后在other变换
publicbooleanpostRotate(floatdegrees)
相当于这样:
Matrixother=newMatrix(); other.setRotate(degrees); postConcat(other);
先创建设置一个以0,0为原点旋转degrees度的矩阵other,然后将当前的matrix连接到other之后,并且将连接后的值写入当前matrix。
publicbooleanpostRotate(floatdegrees,floatpx,floatpy)
同上,不过改成这样
Matrixother=newMatrix(); other.setRotate(degrees,px,py); postConcat(other);
publicbooleanpostScale(floatsx,floatsy)
同上,无非是改成
other.setScale(sx,sy);
publicbooleanpostScale(floatsx,floatsy,floatpx,floatpy)
同上
publicbooleanpostSkew(floatkx,floatky)
publicbooleanpostSkew(floatkx,floatky,floatpx,floatpy)
publicbooleanpostTranslate(floatdx,floatdy)
都是一样的,不过是创建的other有所不一样而已
publicbooleanpreConcat(Matrixother)
publicbooleanpreRotate(floatdegrees)
publicbooleanpreRotate(floatdegrees,floatpx,floatpy)
publicbooleanpreScale(floatsx,floatsy)
publicbooleanpreScale(floatsx,floatsy,floatpx,floatpy)
publicbooleanpreSkew(floatkx,floatky)
publicbooleanpreSkew(floatkx,floatky,floatpx,floatpy)
publicbooleanpreTranslate(floatdx,floatdy)
同上边对应的函数功能类似,无非是other被连接在当前matrix之后,然后将连接后的值写入当前matrix当中
publicbooleanrectStaysRect()
如果该matrix可以将rectF变换成rectF,那么该函数返回true,在标准变换,伸缩变换,平移变换,和多个90度的旋转变换时,该函数是返回true的
publicvoidreset()
将当前matrix设置为标准矩阵
publicvoidset(Matrixsrc)
将src的内容深度复制给当前矩阵,如果src为null,那么当前矩阵变为标准矩阵
publicbooleansetConcat(Matrixa,Matrixb)
将当前matrix的值变为a和b的乘积
publicbooleansetPolyToPoly(float[]src,intsrcIndex,float[]dst,intdstIndex,intpointCount)
将当前matrix的值设置为这样的值,对src变换后可以得到dst的数据,pointCount表示点的数目,只能是0-4。设置成功返回true
publicbooleansetRectToRect(RectFsrc,RectFdst,Matrix.ScaleToFitstf)
将当前matrix的值设置为这样的值,对src进行变换后可以得到dst,因两者都是RectF,所以该matrix的值只能是伸缩和平移的组合,设置成功了返回true,stf为伸缩参数,这个Matrix.ScaleToFit伸缩参数有什么名堂呢,它有四个常量,每个常量应用后会导致matrix有什么结果呢,根据那4个常量的文字说明可知,CENTER,END,START表示得到的伸缩矩阵m,m对src进行变换后得到dst1,dst1跟src有同样的宽高比例,dst1在dst的内部,不同的地方是CENTER的状态是这样的:dst1.left-dst.left=dst.right-dst1.right,dst1.top-dst.top=dst.bottom-dst1.bottomEND的状态是这样的:dst1.right=dst.right,dst1.bottom=dst.bottom.START的状态是这样的:dst1.left=dst.left,dst1.top=dst.top;至于FILL表示得到的伸缩矩阵m,通过它对src变换后得到的Rect就是dst,完全重合。结论通过RectF(0,0,10,10), RectF(0,0,20,30)这两个矩阵得到了验证。
publicvoidsetRotate(floatdegrees)
设置当前matrix,使作用于点坐标时使点坐标以点(0,0)为原点旋转degrees度。
publicvoidsetRotate(floatdegrees,floatpx,floatpy)
设置当前matrix,使作用于点坐标时使点坐标以点(px,py)为原点旋转degrees度。在转换过程中,该原点不可改变
publicvoidsetScale(floatsx,floatsy,floatpx,floatpy)
设置当前matrix,使作用于点坐标时使点坐标以(px,py)为支点伸缩sx,sy倍。(px,py)在转换过程中不能改变。这个解释有点蒙,验证了下发现其实就是x'=(x+px)*sx,y'=(y+py)*sy
publicvoidsetScale(floatsx,floatsy)
这其实就是setScale(sx,sy,0,0);
publicvoidsetSinCos(floatsinValue,floatcosValue)
这其实就是setSinCos(sinValue,cosValue,0,0);
publicvoidsetSinCos(floatsinValue,floatcosValue,floatpx,floatpy)
设置当前matrix,以px,py为支点进行旋转变换,变换方式与sinValue,cosValue的值有关,经过验证,可以得到近似换算公式为:
x'=cosValue*x-sinValue*y+(1-cosValue)*px+sinValue*py; y'=sinValue*x+cosValue*y-sinValue*px+(1-cosValue)*py;
publicvoidsetSkew(floatkx,floatky,floatpx,floatpy)
设置当前matrix,以px,py为支点进行倾斜kx,ky.公式变换应该为
x'=x+kx*(y-py),y'=ky*(x-px)+y;
publicvoidsetSkew(floatkx,floatky)
相当于setSkew(kx,ky,0,0);
publicvoidsetTranslate(floatdx,floatdy)
设置matrix,应用时使点坐标(x,y)各自平移为(x+dx,y+dy);
publicvoidsetValues(float[]values)
复制9个数据给matrix,由于matrix的变形,或许这些数据会变成16位的数据,所以用getValues()可能不能得到与初始化相同的数据。不出意外的话,values的后三位要是0,0,1,否则可能该matrix变化后得不到你想要的点坐标
publicStringtoShortString()
publicStringtoString()
返回一个字符串用来描述该目标和数据,该类的子类是鼓励重写该函数的,详细描述该对象的类型和数据。默认的描述方式如下
getClass().getName()+'@'+Integer.toHexString(hashCode())
补充源码如下
packagecom.hahajlu; importAndroid.app.Activity; importandroid.content.Context; importandroid.graphics.Canvas; importandroid.graphics.Color; importandroid.graphics.Matrix; importandroid.graphics.Paint; importandroid.graphics.RectF; importandroid.os.Bundle; importandroid.view.View; publicclassMatrixActivityextendsActivity{ /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(newSampleView(this)); } } classSampleViewextendsView { Matrixmt1=newMatrix(); Matrixmt2=newMatrix(); publicSampleView(Contextcontext) { super(context); } @Override protectedvoidonDraw(Canvascanvas){ //TODOAuto-generatedmethodstub floatp[]=newfloat[]{100.f,100.f}; //mt1.setRotate(90); mt1.setValues(newfloat[]{1,0,1,0,1,3,1,2,1}); //mt1.mapPoints(p); //mt1.setScale(0.5f,0.5f); //mt1.mapPoints(p); //mt1.setTranslate(10.f,10.f); //mt1.invert(mt2); //mt1.setRectToRect(newRectF(0,0,10,10),newRectF(0,0,20,30),Matrix.ScaleToFit.FILL); //mt1.setScale(0.5f,0.5f,20f,30f); //mt1.setSinCos(0.5f,0.6f,30.f,20.f); //mt1.setSkew(10f,15f,20f,32f); floatvalues[]=newfloat[9]; mt1.getValues(values); mt1.mapPoints(p); Paintpaint=newPaint(); paint.setColor(Color.BLACK); canvas.drawColor(Color.WHITE); canvas.drawText("为了",p[0],p[1],paint); System.out.println("x="+p[0]+"y="+p[1]); for(inti=0;i<9;i++) System.out.println("values="+values[i]); //floatradiu=mt1.mapRadius(10.f); //System.out.println("radiu="+radiu); super.onDraw(canvas); } }
希望本文所述对大家Android程序设计有所帮助。