android实现皮克定理


废话少说代码备注很详细,直接上代码。

1.画图工具类

public class LogicView extends View {
    //背景点集合
    private ArrayList<Circle> bgCircles;
    //所有线的集合
    private ArrayList<Line> allLines;
    private Paint bgPaint;
    private Paint linePaint;
    public static final int LINE_TAG=1;
    public static final int MOVE_TAG=2;
    private int currOperateTag=LINE_TAG;
    public LogicView(Context context) {
        super(context);
        initData();
        initView();
    }

    public LogicView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initData();
        initView();
    }

    private void initData() {
        bgCircles=new ArrayList<>();
        allLines=new ArrayList<>();
    }

    public ArrayList<Line> getAllLines() {
        return allLines;
    }

    private void initView() {
        bgPaint=new Paint();
        bgPaint.setAntiAlias(true);
        bgPaint.setColor(Color.BLACK);

        linePaint=new Paint();
        linePaint.setAntiAlias(true);
        linePaint.setStrokeWidth(2);
        linePaint.setColor(Color.RED);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //canvas.drawColor(Color.WHITE);
        canvas.drawColor(Color.argb(255,223,233,223));
        for (int i=0;i<bgCircles.size();i++){
            Circle circle=bgCircles.get(i);
            canvas.drawCircle(circle.getX(),circle.getY(),circle.getR(),bgPaint);
        }
        for (int i=0;i<allLines.size();i++){
            Line line=allLines.get(i);
            canvas.drawLine(bgCircles.get(line.startCirclePosition).x,bgCircles.get(line.startCirclePosition).y,
                    bgCircles.get(line.endCirclePosition).x,bgCircles.get(line.endCirclePosition).y,linePaint);
        }
    }
    /**
     * 画底部点
     * author LH
     * date 2016/11/25 17:47
     */
    public void setBgCircle(ArrayList<Circle> bgCircles){
        this.bgCircles=bgCircles;
        postInvalidate();
    }
    /**
     * 清空画的线
     * author LH
     * date 2016/11/25 18:45
     */
    public void clear() {
        allLines.clear();
        tag=DOWN;
        currOperateTag=LINE_TAG;
        postInvalidate();
    }
    /**
     * 整体放大或者缩小
     * author LH
     * date 2016/11/28 10:02
     *
     */
    public void changeZoom(int row,float twoPointW,float twoPointH) {
        int centerPosition = getCenterNearPoint();
        int centerRow = centerPosition / row;
        int centerLine = centerPosition % row;
        for (int i = 0; i < bgCircles.size(); i++) {
            int currentRow = i / row;
            int currentLine = i % row;
            bgCircles.get(i).x = bgCircles.get(centerPosition).x - (centerLine - currentLine) * twoPointW;
            bgCircles.get(i).y = bgCircles.get(centerPosition).y - (centerRow - currentRow) * twoPointH;
        }
        Log.e("allLines", allLines.toString());
        postInvalidate();
    }
    /**
     * 设置当前的操作
     * author LH
     * date 2016/11/25 18:52
     */
    public void setCurrOperateTag(int currOperateTag) {
        this.currOperateTag = currOperateTag;
    }
    /**
     * 画移动时的临时直线
     * author LH
     * date 2016/11/25 20:07
     */
    public void drawMoveLine(Line line){
        if(tag==DOWN){
            allLines.add(line);
        }else {
            allLines.set(allLines.size() - 1,line);
        }
        postInvalidate();
    }
    /**
     * 求两点之间的距离
     * author LH
     * date 2016/11/25 17:06
     */
    private float twoPointW(float moveX,float moveY,float toX,float toY){
        return (float) Math.sqrt(Math.pow(moveX-toX,2)+Math.pow(moveY-toY,2));
    }
    /**
     * 获取距离目标点最近的点的位置
     * author LH
     * date 2016/11/25 17:32
     */
    private int getNearestCircle(float moveX,float moveY){
        int point=0;
        float near=twoPointW(moveX,moveY,bgCircles.get(0).x,bgCircles.get(0).y);
        for (int i=0;i<bgCircles.size();i++){
            float currentW=twoPointW(moveX,moveY,bgCircles.get(i).x,bgCircles.get(i).y);
            if(near>currentW){
                near=currentW;
                point=i;
            }
        }
        return point;
    }
    /**
     * 获取画线的中心点的相近的点
     * author LH
     * date 2016/11/28 10:44
     * @return 点的位置
     */
    public int getCenterNearPoint(){
        if(allLines.size()>0) {
            float nearX = bgCircles.get(allLines.get(0).startCirclePosition).x;
            float nearY = bgCircles.get(allLines.get(0).startCirclePosition).y;
            float farX = bgCircles.get(allLines.get(0).startCirclePosition).x;
            float farY = bgCircles.get(allLines.get(0).startCirclePosition).y;
            for (int i = 0; i < allLines.size(); i++) {
                Line line = allLines.get(i);
                if (nearX > bgCircles.get(line.startCirclePosition).x) {
                    nearX = bgCircles.get(line.startCirclePosition).x;
                }
                if (nearX > bgCircles.get(line.endCirclePosition).x) {
                    nearX = bgCircles.get(line.endCirclePosition).x;
                }
                if (nearY > bgCircles.get(line.startCirclePosition).y) {
                    nearY = bgCircles.get(line.startCirclePosition).y;
                }
                if (nearY > bgCircles.get(line.endCirclePosition).y) {
                    nearY = bgCircles.get(line.endCirclePosition).y;
                }
                if (farX < bgCircles.get(line.startCirclePosition).x) {
                    farX = bgCircles.get(line.startCirclePosition).x;
                }
                if (farX < bgCircles.get(line.endCirclePosition).x) {
                    farX = bgCircles.get(line.endCirclePosition).x;
                }
                if (farY < bgCircles.get(line.startCirclePosition).y) {
                    farY = bgCircles.get(line.startCirclePosition).y;
                }
                if (farY < bgCircles.get(line.endCirclePosition).y) {
                    farY = bgCircles.get(line.endCirclePosition).y;
                }
            }
            float centerX = (nearX + farX) / 2;
            float centerY = (nearY + farY) / 2;
            return getNearestCircle(centerX, centerY);
        }else {
            return bgCircles.size()/2;
        }
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (currOperateTag) {
            case LINE_TAG:
                lineOperate(event);
                break;
            case MOVE_TAG:
                if(allLines.size()>0) {
                    moveOperate(event);
                }
                break;
        }
        return true;
    }
    ArrayList<LinePoint> linePoints;
    int down_nearPoint,up_nearPoint,move_nearPoint;
    private void moveOperate(MotionEvent event) {
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                float x_down = event.getRawX();
                float y_down = event.getRawY();
                down_nearPoint = getNearestLinePoints(x_down,y_down);
                Log.e("getNearestLinePoints",linePoints.toString());
                break;
            case MotionEvent.ACTION_UP:
                break;
            case MotionEvent.ACTION_MOVE:
                float x_move = event.getRawX();
                float y_move = event.getRawY();
                move_nearPoint = getNearestCircle(x_move, y_move);
                drawMoveLinePoint(move_nearPoint);
                break;
        }
    }
    /**
     * 画拖动时的直线
     * author LH
     * date 2016/11/26 15:54
     */
    private void drawMoveLinePoint(int move_nearPoint) {
        for(int i=0;i<linePoints.size();i++){
            LinePoint linePoint=linePoints.get(i);
            Line addLine;
            if(linePoint.type==0){
                addLine=new Line(move_nearPoint,linePoint.line.endCirclePosition);
            }else {
                addLine=new Line(linePoint.line.startCirclePosition,move_nearPoint);
            }
            allLines.set(linePoint.position,addLine);
        }
        postInvalidate();
    }

    /**
     * 获取拉伸是距离点击点最近的直线
     * author LH
     * date 2016/11/26 10:50
     */
    private int getNearestLinePoints(float x_down, float y_down) {
        linePoints=new ArrayList<>();
        int position=allLines.get(0).startCirclePosition;
        float near=twoPointW(x_down,y_down,bgCircles.get(allLines.get(0).startCirclePosition).x,bgCircles.get(allLines.get(0).startCirclePosition).y);
        for (int i=0;i<allLines.size();i++){
            float currentStart=twoPointW(x_down,y_down,bgCircles.get(allLines.get(i).startCirclePosition).x,bgCircles.get(allLines.get(i).startCirclePosition).y);
            float currentEnd=twoPointW(x_down,y_down,bgCircles.get(allLines.get(i).endCirclePosition).x,bgCircles.get(allLines.get(i).endCirclePosition).y);
            if (near>currentStart){
                near=currentStart;
                position=allLines.get(i).startCirclePosition;
            }
            if (near>currentEnd){
                near=currentEnd;
                position=allLines.get(i).endCirclePosition;
            }
        }
        for (int i=0;i<allLines.size();i++){
            if(allLines.get(i).startCirclePosition==position){
                LinePoint linePoint=new LinePoint(0,i,allLines.get(i));
                linePoints.add(linePoint);
            }else if(allLines.get(i).endCirclePosition==position){
                LinePoint linePoint=new LinePoint(1,i,allLines.get(i));
                linePoints.add(linePoint);
            }
        }
        return position;
    }
    float x_down,y_down,x_up,y_up;
    int tag=1;
    int DOWN=1,MOVE=2;
    private void lineOperate(MotionEvent event) {
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                x_down = event.getRawX();
                y_down = event.getRawY();
                down_nearPoint = getNearestCircle(x_down, y_down);
                tag=DOWN;
                break;
            case MotionEvent.ACTION_UP:
                x_up = event.getRawX();
                y_up = event.getRawY();
                up_nearPoint = getNearestCircle(x_up, y_up);
                break;
            case MotionEvent.ACTION_MOVE:
                float x_move = event.getRawX();
                float y_move = event.getRawY();
                move_nearPoint = getNearestCircle(x_move, y_move);
                drawMoveLine(new Line(down_nearPoint, move_nearPoint));
                tag=MOVE;
                break;
        }
    }
}
2.调用主函数
public class MainActivity extends Activity {
    @Bind(R.id.logicView)
    LogicView logicView;
    @Bind(R.id.btn_line)
    ImageView btnLine;
    @Bind(R.id.btn_move)
    ImageView btnMove;
    @Bind(R.id.btn_zoomIn)
    ImageView btnZoomIn;
    @Bind(R.id.btn_zoomOut)
    ImageView btnZoomOut;
    @Bind(R.id.btn_clean)
    ImageView btnClean;
    @Bind(R.id.activity_main)
    RelativeLayout activityMain;
    private ArrayList<Circle> bgCircles;
    private float rightBtnW = 150;//右侧按钮宽度
    private float bottomH = 20;//底部宽度
    private int bgPointRow = 24;//背景的行数
    private int bgPointLine = 15;//背景的列数
    float useW,useH;
    private double allZooms[]=new double[]{1.2,1.5,1.8,2.0,2.2,2.5,2.8,3.0};
    private int currentZoom=0;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        btnLine.setSelected(true);
        btnMove.setSelected(false);
        getBgCirclePosition();
        logicView.setBgCircle(bgCircles);
    }

    /**
     * 设置背景圆的坐标和半径
     * author LH
     * date 2016/11/25 16:06
     */
    private void getBgCirclePosition() {
        bgCircles = new ArrayList<>();
        WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
        int width = wm.getDefaultDisplay().getWidth();
        int height = wm.getDefaultDisplay().getHeight();
        Log.e("position", "width:" + width + " height:" + height);
        useW = width - rightBtnW;
        useH = height - bottomH;
        for (int j = 0; j < bgPointLine; j++) {
            for (int i = 0; i < bgPointRow; i++) {
                Circle circle = new Circle(useW / (bgPointRow + 1) * (i + 1), useH / (bgPointLine + 1) * (j + 1), 5);
                bgCircles.add(circle);
            }
        }
    }
    @OnClick({R.id.btn_line, R.id.btn_move, R.id.btn_zoomIn, R.id.btn_zoomOut, R.id.btn_clean})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_line:
                btnLine.setSelected(true);
                btnMove.setSelected(false);
                logicView.setCurrOperateTag(LogicView.LINE_TAG);
                break;
            case R.id.btn_move:
                btnLine.setSelected(false);
                btnMove.setSelected(true);
                logicView.setCurrOperateTag(LogicView.MOVE_TAG);
                break;
            case R.id.btn_zoomIn:
                if(currentZoom<allZooms.length-1) {
                    currentZoom++;
                    logicView.changeZoom(bgPointRow, (float) (useW / (bgPointRow + 1) * allZooms[currentZoom]), (float) (useH / (bgPointLine + 1) * allZooms[currentZoom]));
                }
                break;
            case R.id.btn_zoomOut:
                if(currentZoom>0) {
                    currentZoom--;
                    logicView.changeZoom(bgPointRow, (float) (useW / (bgPointRow + 1) * allZooms[currentZoom]), (float) (useH / (bgPointLine + 1) * allZooms[currentZoom]));
                }
                break;
            case R.id.btn_clean:
                btnLine.setSelected(true);
                btnMove.setSelected(false);
                logicView.setCurrOperateTag(LogicView.LINE_TAG);
                currentZoom=0;
                getBgCirclePosition();
                logicView.setBgCircle(bgCircles);
                logicView.clear();
                break;
        }
    }
}

3.用到的实体类

/**
 * Created by LH on 2016/11/25.
 */

public class Circle {
    float x;
    float y;
    float r;

    public Circle(float x, float y, float r) {
        this.x = x;
        this.y = y;
        this.r = r;
    }

    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }

    public float getR() {
        return r;
    }
}
/**
 * Created by LH on 2016/11/25.
 */

public class Line {
    //起始的点的位置
    int startCirclePosition;
    //终止点的位置
    int endCirclePosition;

    public Line(int startCirclePosition, int endCirclePosition) {
        this.startCirclePosition = startCirclePosition;
        this.endCirclePosition = endCirclePosition;
    }

    @Override
    public String toString() {
        return "Line{" +
                "startCirclePosition=" + startCirclePosition +
                ", endCirclePosition=" + endCirclePosition +
                '}';
    }
}
/**
 * Created by LH on 2016/11/26.
 */

public class LinePoint {
    //0起点 1终点
    int type;
    //直线在集合中的位置
    int position;
    //直线
    Line line;

    public LinePoint(int type, int position, Line line) {
        this.type = type;
        this.position = position;
        this.line = line;
    }

    @Override
    public String toString() {
        return "LinePoint{" +
                "type=" + type +
                ", position=" + position +
                ", line=" + line +
                '}';
    }
}

4.布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.lh.pointpicture.MainActivity">
    <RelativeLayout
        android:id="@+id/rl_control"
        android:layout_width="150px"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:background="#606060">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_centerVertical="true"
            android:layout_centerHorizontal="true"
            android:gravity="center_horizontal">
            <ImageView
                android:id="@+id/btn_line"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/zhixian_selector"/>
            <ImageView
                android:id="@+id/btn_move"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:background="@drawable/yidong_selector"/>
            <ImageView
                android:id="@+id/btn_zoomIn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:background="@drawable/fangda_selector"/>
            <ImageView
                android:id="@+id/btn_zoomOut"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:background="@drawable/suoxia_selector"/>
            <ImageView
                android:id="@+id/btn_clean"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:background="@drawable/chongzuo_selector"/>
        </LinearLayout>
    </RelativeLayout>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_toLeftOf="@id/rl_control">
        <com.example.lh.pointpicture.LogicView
            android:id="@+id/logicView"
            android:layout_width="1130px"
            android:layout_height="800px"
            android:layout_centerInParent="true"
            android:clickable="true"/>
    </RelativeLayout>
</RelativeLayout>




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值