Java 通过Renderscript加速处理低多边形 什么是低保利?

Java 通过Renderscript加速处理低多边形 什么是低保利?,java,android,bitmap,renderscript,Java,Android,Bitmap,Renderscript,德洛奈 我用java实现了Delaunay算法;但是它非常慢。在我的电脑中,将位图处理为低多边形大约需要4-9秒。在安卓手机中,情况要糟糕得多。即使我调整输入位图的大小,也需要大约1-2分钟 实施 final class Delaunay{ 私有静态int[][]超三角形(列出顶点){ int xMin=Integer.MAX_值; int yMin=整数的最大值; int xMax=Integer.MIN_值; int yMax=Integer.MIN_值; 浮点dx,dy,dmax,xmid

德洛奈 我用java实现了
Delaunay
算法;但是它非常慢。在我的电脑中,将位图处理为低多边形大约需要4-9秒。在安卓手机中,情况要糟糕得多。即使我调整输入位图的大小,也需要大约1-2分钟

实施
final class Delaunay{
私有静态int[][]超三角形(列出顶点){
int xMin=Integer.MAX_值;
int yMin=整数的最大值;
int xMax=Integer.MIN_值;
int yMax=Integer.MIN_值;
浮点dx,dy,dmax,xmid,ymid;
对于(int i=顶点.size()-1;i>=0;i--){
int[]p=顶点。获取(i);
如果(p[0]xMax)xMax=p[0];
如果(p[1]yMax)yMax=p[1];
}
dx=xMax-xMin;
dy=yMax-yMin;
dmax=数学最大值(dx,dy);
xmid=(xMin+dx*0.5f);
ymid=(yMin+dy*0.5f);
返回新的int[][{{(int)(xmid-20*dmax),(int)(ymid-dmax)},
{(int)xmid,(int)(ymid+20*dmax)},
{(int)(xmid+20*dmax),(int)(ymid-dmax)};
}
私有静态外圆(列出顶点、int i、int j、int k){
int x1=顶点。获取(i)[0];
int y1=顶点。获取(i)[1];
int x2=顶点。获取(j)[0];
int y2=顶点。get(j)[1];
int x3=顶点。获取(k)[0];
int y3=顶点。get(k)[1];
int fabsy1y2=数学绝对值(y1-y2);
int fabsy2y3=数学绝对值(y2-y3);
浮点数xc,yc,m1,m2,mx1,mx2,my1,my2,dx,dy;
if(fabsy1y2==0){
m2=-((浮动)(x3-x2)/(y3-y2));
mx2=(x2+x3)/2f;
my2=(y2+y3)/2f;
xc=(x2+x1)/2f;
yc=m2*(xc-mx2)+my2;
}else如果(fabsy2y3==0){
m1=-((浮动)(x2-x1)/(y2-y1));
mx1=(x1+x2)/2f;
my1=(y1+y2)/2f;
xc=(x3+x2)/2f;
yc=m1*(xc-mx1)+my1;
}否则{
m1=-((浮动)(x2-x1)/(y2-y1));
m2=-((浮动)(x3-x2)/(y3-y2));
mx1=(x1+x2)/2f;
mx2=(x2+x3)/2f;
my1=(y1+y2)/2f;
my2=(y2+y3)/2f;
xc=(m1*mx1-m2*mx2+my2-my1)/(m1-m2);
yc=(fabsy1y2>fabsy2y3)?
m1*(xc-mx1)+my1:
m2*(xc-mx2)+my2;
}
dx=x2-xc;
dy=y2-yc;
返回新的外圆(i,j,k,xc,yc,(dx*dx+dy*dy));
}
专用静态无效重复数据消除(ArrayList边缘){
int a,b,m,n;
对于(int j=edges.size();j>0;){
而(j>edges.size()){
j--;
}
if(j0;){
n=边。获取(--i);
m=边。获取(--i);
if((a==m&&b==n)| |(a==n&&b==m)){
如果(j+1=0;i--){
指数[i]=i;
}
sort(索引,新的比较器(){
@凌驾
公共整数比较(整数lhs、整数rhs){
返回顶点.get(rhs)[0]-顶点.get(lhs)[0];
}
});
int[][]st=超三角形(顶点);
顶点。添加(st[0]);
添加(st[1]);
添加(st[2]);
ArrayList open=新建ArrayList();
添加(外圆(顶点,n,n+1,n+2));
ArrayList closed=新建ArrayList();
ArrayList Edge=新的ArrayList();
对于(int i=index.length-1;i>=0;i--){
int c=指数[i];
对于(int j=open.size()-1;j>=0;j--){
外接圆cj=打开。获取(j);
int[]vj=顶点。get(c);
浮点数dx=vj[0]-cj.x;
浮点数dy=vj[1]-cj.y;
如果(dx>0&&dx*dx+dy*dy>cj.r){
关闭。添加(cj);
打开。移除(j);
继续;
}
如果(dx*dx+dy*dy-cj.r>0){
继续;
}
添加(cj.i);
添加(cj.j);
添加(cj.j);
添加(cj.k);
添加(cj.k);
添加(cj.i);
打开。移除(j);
}
重复数据消除(边缘);
对于(int j=edges.size();j>0;){
int b=边。get(--j);
int a=边。get(--j);
int x1=顶点。获取(a)[0];
inty1=顶点。获取(a)[1];
int x2=顶点。获取(b)[0];
int y2=顶点。get(b)[1];
int x3=顶点。获取(c)[0];
int y3=顶点。get(c)[1];
布尔hasCircular=true;
如果((x1==x2)和&(x1==x3)| |((y1==y2)和&(y1==y3))){
HasCircular=假;
}
if(hasCircular){
添加(外圆(顶点,a,b,c));
}
}
边。清除();
}
对于(int i=open.size()-1;i>=0;i--){
closed.add(open.get(i));
}
open.clear();
ArrayList out=新的ArrayList();

对于(inti=0;i摘要:您至少应该尝试一下C版本,看看它有多有效

RenderScript是关于并行化问题的,这样CPU或GPU上的许多不同的工作单元都可以处理数据。但这意味着,您要在RenderScript中实现的算法必须最小化循环和条件。只需查看上面的代码,就会看到许多循环和if语句,在我看来确实如此无法很好地移植到RenderScript

快速搜索将显示大量关于并行化Del的学术论文
 final class Delaunay {


private static int[][] supertriangle(List<int[]> vertices) {
    int xMin = Integer.MAX_VALUE;
    int yMin = Integer.MAX_VALUE;
    int xMax = Integer.MIN_VALUE;
    int yMax = Integer.MIN_VALUE;

    float dx, dy, dmax, xmid, ymid;


    for (int i = vertices.size() - 1; i >= 0; i--) {
        int[] p = vertices.get(i);
        if (p[0] < xMin) xMin = p[0];
        if (p[0] > xMax) xMax = p[0];
        if (p[1] < yMin) yMin = p[1];
        if (p[1] > yMax) yMax = p[1];
    }

    dx = xMax - xMin;
    dy = yMax - yMin;

    dmax = Math.max(dx, dy);

    xmid = (xMin + dx * 0.5f);
    ymid = (yMin + dy * 0.5f);

    return new int[][]{{(int) (xmid - 20 * dmax), (int) (ymid - dmax)},
            {(int) xmid, (int) (ymid + 20 * dmax)},
            {(int) (xmid + 20 * dmax), (int) (ymid - dmax)}};
}

private static Circumcircle circumcircle(List<int[]> vertices, int i, int j, int k) {
    int x1 = vertices.get(i)[0];
    int y1 = vertices.get(i)[1];
    int x2 = vertices.get(j)[0];
    int y2 = vertices.get(j)[1];
    int x3 = vertices.get(k)[0];
    int y3 = vertices.get(k)[1];


    int fabsy1y2 = Math.abs(y1 - y2);
    int fabsy2y3 = Math.abs(y2 - y3);

    float xc, yc, m1, m2, mx1, mx2, my1, my2, dx, dy;


    if (fabsy1y2 == 0) {
        m2 = -((float) (x3 - x2) / (y3 - y2));
        mx2 = (x2 + x3) / 2f;
        my2 = (y2 + y3) / 2f;
        xc = (x2 + x1) / 2f;
        yc = m2 * (xc - mx2) + my2;
    } else if (fabsy2y3 == 0) {
        m1 = -((float) (x2 - x1) / (y2 - y1));
        mx1 = (x1 + x2) / 2f;
        my1 = (y1 + y2) / 2f;
        xc = (x3 + x2) / 2f;
        yc = m1 * (xc - mx1) + my1;
    } else {
        m1 = -((float) (x2 - x1) / (y2 - y1));
        m2 = -((float) (x3 - x2) / (y3 - y2));
        mx1 = (x1 + x2) / 2f;
        mx2 = (x2 + x3) / 2f;
        my1 = (y1 + y2) / 2f;
        my2 = (y2 + y3) / 2f;
        xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2);
        yc = (fabsy1y2 > fabsy2y3) ?
                m1 * (xc - mx1) + my1 :
                m2 * (xc - mx2) + my2;
    }

    dx = x2 - xc;
    dy = y2 - yc;

    return new Circumcircle(i, j, k, xc, yc, (dx * dx + dy * dy));
}

private static void dedup(ArrayList<Integer> edges) {
    int a, b, m, n;
    for (int j = edges.size(); j > 0; ) {
        while (j > edges.size()) {
            j--;
        }
        if (j <= 0) {
            break;
        }
        b = edges.get(--j);
        a = edges.get(--j);

        for (int i = j; i > 0; ) {
            n = edges.get(--i);
            m = edges.get(--i);

            if ((a == m && b == n) || (a == n && b == m)) {
                if (j + 1 < edges.size())
                    edges.remove(j + 1);
                edges.remove(j);
                if (i + 1 < edges.size())
                    edges.remove(i + 1);
                edges.remove(i);
                break;
            }
        }
    }
}

static List<Integer> triangulate(final List<int[]> vertices) {
    int n = vertices.size();

    if (n < 3) {
        return new ArrayList<>();
    }

    Integer[] indices = new Integer[n];

    for (int i = n - 1; i >= 0; i--) {
        indices[i] = i;
    }


    Arrays.sort(indices, new Comparator<Integer>() {
        @Override
        public int compare(Integer lhs, Integer rhs) {
            return vertices.get(rhs)[0] - vertices.get(lhs)[0];
        }
    });
    int[][] st = supertriangle(vertices);

    vertices.add(st[0]);
    vertices.add(st[1]);
    vertices.add(st[2]);

    ArrayList<Circumcircle> open = new ArrayList<>();
    open.add(circumcircle(vertices, n, n + 1, n + 2));

    ArrayList<Circumcircle> closed = new ArrayList<>();

    ArrayList<Integer> edges = new ArrayList<>();

    for (int i = indices.length - 1; i >= 0; i--) {

        int c = indices[i];

        for (int j = open.size() - 1; j >= 0; j--) {

            Circumcircle cj = open.get(j);
            int[] vj = vertices.get(c);

            float dx = vj[0] - cj.x;
            float dy = vj[1] - cj.y;

            if (dx > 0 && dx * dx + dy * dy > cj.r) {
                closed.add(cj);
                open.remove(j);
                continue;
            }


            if (dx * dx + dy * dy - cj.r > 0) {
                continue;
            }

            edges.add(cj.i);
            edges.add(cj.j);
            edges.add(cj.j);
            edges.add(cj.k);
            edges.add(cj.k);
            edges.add(cj.i);

            open.remove(j);
        }

        dedup(edges);

        for (int j = edges.size(); j > 0; ) {
            int b = edges.get(--j);
            int a = edges.get(--j);

            int x1 = vertices.get(a)[0];
            int y1 = vertices.get(a)[1];
            int x2 = vertices.get(b)[0];
            int y2 = vertices.get(b)[1];
            int x3 = vertices.get(c)[0];
            int y3 = vertices.get(c)[1];

            boolean hasCircumcircle = true;
            if ((x1==x2)&&(x1==x3) || ((y1==y2)&&(y1==y3))){
                hasCircumcircle = false;
            }
            if (hasCircumcircle) {
                open.add(circumcircle(vertices, a, b, c));
            }
        }

        edges.clear();

    }

    for (int i = open.size() - 1; i >= 0; i--) {
        closed.add(open.get(i));
    }

    open.clear();

    ArrayList<Integer> out = new ArrayList<>();

    for (int i = 0; i <closed.size(); i++) {
        Circumcircle ci = closed.get(i);
        if (ci.i < n && ci.j < n && ci.k < n) {
            out.add(ci.i);
            out.add(ci.j);
            out.add(ci.k);
        }
    }
    return out;
}

private static class Circumcircle {
    public int i, j, k;
    float x, y, r;

    public Circumcircle(int i, int j, int k, float x, float y, float r) {
        this.i = i;
        this.j = j;
        this.k = k;
        this.x = x;
        this.y = y;
        this.r = r;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Circumcircle){
            Circumcircle circumcircle = (Circumcircle) obj;
            if (x==circumcircle.x && y==circumcircle.y && r==circumcircle.r)
                return true;
        }
        return super.equals(obj);
    }
}


}