zoukankan      html  css  js  c++  java
  • android Graphics(三):区域(Range)

    前言:最近几天对画图的研究有些缓慢,项目开始写代码了,只能在晚上空闲的时候捯饬一下自己的东西,今天给大家讲讲区域的相关知识,已经想好后面两篇的内容了,这几天有时间赶紧写出来给大家。有关界面开发的东东内容确实比较多,慢慢来吧,总有一天会不一样。

     

    我自己的一句警言,送给大家:

    想要跟别人不一样,你就要跟别人不一样。----- Harvic 

     

     

    相关文章:

    1、《android Graphics(一):概述及基本几何图形绘制》
    2、《android Graphics(二):路径及文字》
    3、《android Graphics(三):区域(Range)》
    4、《android Graphics(四):canvas变换与操作》

    一、构造Region

    1、基本构造函数

     public Region()  //创建一个空的区域  
     public Region(Region region) //拷贝一个region的范围  
     public Region(Rect r)  //创建一个矩形的区域  
     public Region(int left, int top, int right, int bottom) //创建一个矩形的区域  

    上面的四个构造函数,第一个还要配合其它函数使用,暂时不提。
    第二个构造函数是通过其它的Region来复制一个同样的Region变量
    第三个,第四个才是正规常的,根据一个矩形或矩形的左上角和右下角点构造出一个矩形区域

    2、间接构造

     public void setEmpty()  //置空
     public boolean set(Region region)   
     public boolean set(Rect r)   
     public boolean set(int left, int top, int right, int bottom)   
     public boolean setPath(Path path, Region clip)//后面单独讲

    这是Region所具有的一系列Set方法,我这里全部列了出来,下面一一对其讲解:
    注意:无论调用Set系列函数的Region是不是有区域值,当调用Set系列函数后,原来的区域值就会被替换成Set函数里的区域。
    SetEmpty():从某种意义上讲置空也是一个构造函数,即将原来的一个区域变量变成了一个空变量,要再利用其它的Set方法重新构造区域。
    set(Region region):利用新的区域值来替换原来的区域
    set(Rect r):利用矩形所代表的区域替换原来的区域
    set(int left, int top, int right, int bottom):同样,根据矩形的两个点构造出矩形区域来替换原来的区域值
    setPath(Path path, Region clip):根据路径的区域与某区域的交集,构造出新区域,这个后面具体讲解

    举个小例子,来说明一个Set系列函数的替换概念:

    关于重写新建一个类,并派生自view,并且要重写OnDraw函数的问题我就不再讲了,有问题的同学,可以参考下《android Graphics(一):概述及基本几何图形绘制》,当然最后我也会给出相关的源码,直接看源码也行。

    下面写了一个函数,先把Set函数注释起来,看看画出来的区域的位置,然后开启Set函数,然后再看画出来的区域
    注:里面有个函数drawRegion(Canvas canvas,Region rgn,Paint paint),只知道它可以画出指定的区域就可以了,具体里面是什么意思,后面我们再仔细讲。

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. public class MyRegionView extends View {  
    2.   
    3.     public MyRegionView(Context context) {  
    4.         super(context);  
    5.         // TODO Auto-generated constructor stub  
    6.     }  
    7.       
    8.     @Override  
    9.     protected void onDraw(Canvas canvas) {  
    10.         // TODO Auto-generated method stub  
    11.         super.onDraw(canvas);  
    12.           
    13.         //初始化画笔  
    14.         Paint paint = new Paint();  
    15.         paint.setColor(Color.RED);  
    16.         paint.setStyle(Style.FILL);  
    17.         paint.setStrokeWidth(2);  
    18.           
    19.         Region rgn = new Region(10,10,100,100);  
    20.   
    21. //      rgn.set(100, 100, 200, 200);  
    22.         drawRegion(canvas, rgn, paint);  
    23.           
    24.     }  
    25.       
    26.     //这个函数不懂没关系,下面会细讲  
    27.     private void drawRegion(Canvas canvas,Region rgn,Paint paint)  
    28.     {  
    29.         RegionIterator iter = new RegionIterator(rgn);  
    30.         Rect r = new Rect();  
    31.           
    32.         while (iter.next(r)) {  
    33.           canvas.drawRect(r, paint);  
    34.         }   
    35.     }  
    36.   
    37. }  

    看下效果:
                                未开启Set函数时                                                                                           

                           使用Set函数后,替换为新区域

    3、使用SetPath()构造不规则区域

    boolean setPath (Path path, Region clip)

    参数说明:
    Path path:用来构造的区域的路径
    Region clip:与前面的path所构成的路径取交集,并将两交集设置为最终的区域

    由于路径有很多种构造方法,而且可以轻意构造出非矩形的路径,这就摆脱了前面的构造函数只能构造矩形区域的限制。但这里有个问题是要指定另一个区域来取共同的交集,当然如果想显示路径构造的区域,Region clip参数可以传一个比Path范围大的多的区域,取完交集之后,当然是Path参数所对应的区域喽。机智的孩子。

    下面,先构造一个椭圆路径,然后在SetPath时,传进去一个比Path小的矩形区域,让它们两个取交集

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. public class MyRegionView extends View {  
    2.   
    3.     public MyRegionView(Context context) {  
    4.         super(context);  
    5.         // TODO Auto-generated constructor stub  
    6.     }  
    7.       
    8.     @Override  
    9.     protected void onDraw(Canvas canvas) {  
    10.         // TODO Auto-generated method stub  
    11.         super.onDraw(canvas);  
    12.         //初始化Paint  
    13.         Paint paint = new Paint();  
    14.         paint.setColor(Color.RED);  
    15.         paint.setStyle(Style.FILL);  
    16.         paint.setStrokeWidth(2);  
    17.         //构造一个椭圆路径  
    18.         Path ovalPath = new Path();  
    19.         RectF rect =  new RectF(50, 50, 200, 500);    
    20.         ovalPath.addOval(rect, Direction.CCW);  
    21.         //SetPath时,传入一个比椭圆区域小的矩形区域,让其取交集  
    22.         Region rgn = new Region();  
    23.         rgn.setPath(ovalPath,new  Region(50, 50, 200, 200));  
    24.         //画出路径  
    25.         drawRegion(canvas, rgn, paint);  
    26.     }  
    27.       
    28.     //这个函数不懂没关系,下面会细讲  
    29.     private void drawRegion(Canvas canvas,Region rgn,Paint paint)  
    30.     {  
    31.         RegionIterator iter = new RegionIterator(rgn);  
    32.         Rect r = new Rect();  
    33.           
    34.         while (iter.next(r)) {  
    35.           canvas.drawRect(r, paint);  
    36.         }   
    37.     }  
    38. }  

    结果如下:

    二、矩形集枚举区域——RegionIterator类

    对于特定的区域,我们都可以使用多个矩形来表示其大致形状。事实上,如果矩形足够小,一定数量的矩形就能够精确表示区域的形状,也就是说,一定数量的矩形所合成的形状,也可以代表区域的形状。RegionIterator类,实现了获取组成区域的矩形集的功能,其实RegionIterator类非常简单,总共就两个函数,一个构造函数和一个获取下一个矩形的函数;
    RegionIterator(Region region) //根据区域构建对应的矩形集
    boolean next(Rect r) //获取下一个矩形,结果保存在参数Rect r 中

    由于在Canvas中没有直接绘制Region的函数,我们想要绘制一个区域,就只能通过利用RegionIterator构造矩形集来逼近的显示区域。用法如下:

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. private void drawRegion(Canvas canvas,Region rgn,Paint paint)  
    2. {  
    3.     RegionIterator iter = new RegionIterator(rgn);  
    4.     Rect r = new Rect();  
    5.       
    6.     while (iter.next(r)) {  
    7.       canvas.drawRect(r, paint);  
    8.     }   
    9. }  

    上面我们也都看到了它的用法,首先,根据区域构建一个矩形集,然后利用next(Rect r)来逐个获取所有矩形,绘制出来,最终得到的就是整个区域,如果我们将上面的画笔Style从FILL改为STROKE,重新绘制椭圆路径,会看得更清楚。

     

    三、区域的合并、交叉等操作

    无论是区域还是矩形,都会涉及到与另一个区域的一些操作,比如取交集、取并集等,涉及到的函数有:

    public final boolean union(Rect r)   
    public boolean op(Rect r, Op op) {  
    public boolean op(int left, int top, int right, int bottom, Op op)   
    public boolean op(Region region, Op op)   
    public boolean op(Rect rect, Region region, Op op)   

    除了Union(Rect r)是指定合并操作以外,其它四个op()构造函数,都是指定与另一个区域的操作。其中最重要的指定Op的参数,Op的参数有下面四个:

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. 假设用region1  去组合region2     
    2. public enum Op {    
    3.         DIFFERENCE(0), //最终区域为region1 与 region2不同的区域    
    4.         INTERSECT(1), // 最终区域为region1 与 region2相交的区域    
    5.         UNION(2),      //最终区域为region1 与 region2组合一起的区域    
    6.         XOR(3),        //最终区域为region1 与 region2相交之外的区域    
    7.         REVERSE_DIFFERENCE(4), //最终区域为region2 与 region1不同的区域    
    8.         REPLACE(5); //最终区域为为region2的区域    
    9.  }   

    至于这六个参数的具体意义,后面给个具体的图给大家显示出来,先举个取交集的例子。

    效果图:

    先构造两个相交叉的矩形,并画出它们的轮廓

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. //构造两个矩形  
    2. Rect rect1 = new Rect(100,100,400,200);  
    3. Rect rect2 = new Rect(200,0,300,300);  
    4.   
    5. //构造一个画笔,画出矩形轮廓  
    6. Paint paint = new Paint();  
    7. paint.setColor(Color.RED);  
    8. paint.setStyle(Style.STROKE);  
    9. paint.setStrokeWidth(2);  
    10.   
    11. canvas.drawRect(rect1, paint);  
    12. canvas.drawRect(rect2, paint);  

    然后利用上面的两年rect,(rect1和rect2)来构造区域,并在rect1的基础上取与rect2的交集

     

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. //构造两个Region  
    2. Region region = new Region(rect1);  
    3. Region region2= new Region(rect2);  
    4.   
    5. //取两个区域的交集        
    6. region.op(region2, Op.INTERSECT);  

    最后构造一个填充画笔,将所选区域用绿色填充起来

     

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. Paint paint_fill = new Paint();  
    2. paint_fill.setColor(Color.GREEN);  
    3. paint_fill.setStyle(Style.FILL);  
    4. drawRegion(canvas, region, paint_fill);  

    全部代码为:

     

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. /** 
    2.  * created by harvic 
    3.  * 2014/9/4 
    4.  */  
    5. import android.content.Context;  
    6. import android.graphics.Canvas;  
    7. import android.graphics.Color;  
    8. import android.graphics.Paint;  
    9. import android.graphics.Rect;  
    10. import android.graphics.Region;  
    11. import android.graphics.Paint.Style;  
    12. import android.graphics.Region.Op;  
    13. import android.graphics.RegionIterator;  
    14. import android.view.View;  
    15.   
    16. public class MyRegionView extends View {  
    17.   
    18.     public MyRegionView(Context context) {  
    19.         super(context);  
    20.         // TODO Auto-generated constructor stub  
    21.     }  
    22.       
    23.     @Override  
    24.     protected void onDraw(Canvas canvas) {  
    25.         // TODO Auto-generated method stub  
    26.         super.onDraw(canvas);  
    27.           
    28.         //构造两个矩形  
    29.         Rect rect1 = new Rect(100,100,400,200);  
    30.         Rect rect2 = new Rect(200,0,300,300);  
    31.           
    32.         //构造一个画笔,画出矩形轮廓  
    33.         Paint paint = new Paint();  
    34.         paint.setColor(Color.RED);  
    35.         paint.setStyle(Style.STROKE);  
    36.         paint.setStrokeWidth(2);  
    37.           
    38.         canvas.drawRect(rect1, paint);  
    39.         canvas.drawRect(rect2, paint);  
    40.           
    41.           
    42.           
    43.         //构造两个Region  
    44.         Region region = new Region(rect1);  
    45.         Region region2= new Region(rect2);  
    46.   
    47.         //取两个区域的交集        
    48.         region.op(region2, Op.INTERSECT);  
    49.           
    50.         //再构造一个画笔,填充Region操作结果  
    51.         Paint paint_fill = new Paint();  
    52.         paint_fill.setColor(Color.GREEN);  
    53.         paint_fill.setStyle(Style.FILL);  
    54.         drawRegion(canvas, region, paint_fill);  
    55.   
    56.     }  
    57.       
    58.   
    59. private void drawRegion(Canvas canvas,Region rgn,Paint paint)  
    60. {  
    61.     RegionIterator iter = new RegionIterator(rgn);  
    62.     Rect r = new Rect();  
    63.       
    64.     while (iter.next(r)) {  
    65.       canvas.drawRect(r, paint);  
    66.     }   
    67. }  
    68. }  

    其它参数的操作与这个类似,其实只需要改动region.op(region2, Op.INTERSECT);的Op参数值即可,下面就不再一一列举,给出操作后的对比图。


    四、其它一些方法

    Region类除了上面的一些重要的方法以外,还有一些比较容易理解的方法,我就不再一一列举用法了,下面一并列出给大家

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. /**几个判断方法*/    
    2. public native boolean isEmpty();//判断该区域是否为空    
    3. public native boolean isRect(); //是否是一个矩阵    
    4. public native boolean isComplex();//是否是多个矩阵组合    
    5.     
    6.     
    7. /**一系列的getBound方法,返回一个Region的边界*/    
    8. public Rect getBounds()     
    9. public boolean getBounds(Rect r)     
    10. public Path getBoundaryPath()     
    11. public boolean getBoundaryPath(Path path)     
    12.     
    13.     
    14. /**一系列的判断是否包含某点 和是否相交*/    
    15. public native boolean contains(int x, int y);//是否包含某点    
    16. public boolean quickContains(Rect r)   //是否包含某矩阵    
    17. public native boolean quickContains(int left, int top, int right,    
    18.                                         int bottom) //是否没有包含某矩阵    
    19.  public boolean quickReject(Rect r) //是否没和该矩阵相交    
    20.  public native boolean quickReject(int left, int top, int right, int bottom); //是否没和该矩阵相交    
    21.  public native boolean quickReject(Region rgn);  //是否没和该矩阵相交    
    22.     
    23. /**几个平移变换的方法*/    
    24. public void translate(int dx, int dy)     
    25. public native void translate(int dx, int dy, Region dst);    
    26. public void scale(float scale) //hide    
    27. public native void scale(float scale, Region dst);//hide    

    参考文章:《Android 2D Graphics学习(二)、Canvas篇2、Canvas裁剪和Region、RegionIterator》

     

    本篇所涉及到的代码,我集合在了一个工程中,大家可以下载

    源码下载地址:http://download.csdn.net/detail/harvic880925/7866523

    请大家尊重原创者版权,转载请标时出处:http://blog.csdn.net/harvic880925/article/details/39056701   谢谢!

  • 相关阅读:
    【模板】Sparse-Table
    UVa 11235 Frequent values
    【模板】树状数组
    UVa 1428 Ping pong
    数学技巧
    UVa 11300 Spreading the Wealth
    UVa 11729 Commando War
    UVa 11292 Dragon of Loowater
    POJ 3627 Bookshelf
    POJ 1056 IMMEDIATE DECODABILITY
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4507627.html
Copyright © 2011-2022 走看看