我试图获取画布上路径中绘制的所有x,y坐标。但我无法得到积分。我只得到几点。那是为什么?
有什么方法可以得到所有的x和y点吗?
我使用FingerPaint.java作为起点。
Link to Original FingerPaint.java
以下是我修改并使用的代码:
package com.schogini.whiteboard;
import java.util.ArrayList;
import java.util.StringTokenizer;
import android.app.Activity;
import android.content.Context;
import android.graphics.*;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
//import android.widget.Toast;
public class FingerPaint extends Activity implements ColorPickerDialog.OnColorChangedListener {
//color - ARGB
int a = 255;
int r = 255;
int g = 0;
int b = 0;
//erase Flag
boolean eraseFlag=false;
//Internet Posting
static String toSend;
static String parseStr;
//array for storing x,y,r,g,b,a
static ArrayList<String> rArray,gArray,bArray,alphaArray,xPointArray,yPointArray;
//ArrayList<String> rArray_in,gArray_in,bArray_in,alphaArray_in,xPointArray_in,yPointArray_in;
//Drawing types
private static Paint mPaint;
private MaskFilter mEmboss;
private MaskFilter mBlur;
//touch - Path Coordinates
private static float mX;
private static float mY;
//MyView object
MyView m;
//point populate
float dx,dy,distance;
int dd,ii;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
m = new MyView(FingerPaint.this);
setContentView(m);
//move to appropriate module
rArray = new ArrayList<String>();
gArray = new ArrayList<String>();
bArray = new ArrayList<String>();
alphaArray = new ArrayList<String>();
xPointArray = new ArrayList<String>();
yPointArray = new ArrayList<String>();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
//width of the drawing brush
mPaint.setStrokeWidth(12);
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
}
public void parsing(String str22){
//example string received from server
// parseStr = "255,0,0,1.0,88.0,100.0||255,0,0,1.0,88.0,101.0||255,0,0,1.0,88.0,102.0||255,0,0,1.0,88.0,103.0||255,0,0,1.0,88.0,104.0||255,0,0,1.0,88.0,105.0||255,0,0,1.0,88.0,106.0||255,0,0,1.0,88.0,107.0||255,0,0,1.0,88.0,108.0," +
// "||255,0,0,1.0,88.0,109.0||255,0,0,1.0,88.0,110.0||255,0,0,1.0,88.0,111.0||255,0,0,1.0,88.0,112.0||255,0,0,1.0,88.0,113.0||255,0,0,1.0,88.0,114.0||255,0,0,1.0,88.0,115.0||255,0,0,1.0,88.0,116.0||255,0,0,1.0,88.0,117.0," +
// "||255,0,0,1.0,88.0,118.0||255,0,0,1.0,88.0,119.0||255,0,0,1.0,88.0,120.0||255,0,0,1.0,80.0,100.0||255,0,0,1.0,81.0,100.0||255,0,0,1.0,82.0,100.0||255,0,0,1.0,83.0,100.0||255,0,0,1.0,84.0,100.0||255,0,0,1.0,85.0,100.0," +
// "||255,0,0,1.0,86.0,100.0||255,0,0,1.0,87.0,100.0||255,0,0,1.0,88.0,100.0||255,0,0,1.0,89.0,100.0||255,0,0,1.0,91.0,100.0||255,0,0,1.0,92.0,100.0||255,0,0,1.0,93.0,100.0||255,0,0,1.0,94.0,100.0||255,0,0,1.0,95.0,100.0," +
// "||255,0,0,1.0,96.0,100.0||255,0,0,1.0,97.0,100.0||255,0,0,1.0,98.0,100.0||255,0,0,1.0,99.0,100.0||255,0,0,1.0,100.0,100.0||255,0,0,1.0,101.0,100.0||255,0,0,1.0,102.0,100.0||255,0,0,1.0,103.0,100.0,";
parseStr="255,0,0,255,85.351585,90.17996||255,0,0,255,85.351585,90.17996||255,0,0,255,123.97784,80.883064||255,0,0,255,164.47311,71.58616||255,0,0,255,182.22874,65.543175||255,0,0,255,233.9381,48.3439||255,0,0,255,247.95567,42.30091||255,0,0,255,252.62822,40.441532||255,0,0,255,252.62822,40.441532||255,0,0,255,86.9091,167.34427||255,0,0,255,86.9091,167.34427||255,0,0,255,86.9091,167.34427||255,0,0,255,151.70154,133.41057||255,0,0,255,190.3278,118.07068||255,0,0,255,235.18411,98.54717||255,0,0,255,248.57867,92.03935||255,0,0,255,256.36627,89.71512||255,0,0,255,257.30078,89.250275||255,0,0,255,257.30078,89.250275||255,0,0,255,82.548065,277.97742||255,0,0,255,82.548065,277.97742||255,0,0,255,82.548065,277.97742||255,0,0,255,116.50179,258.91876||255,0,0,255,152.63605,240.7898||255,0,0,255,209.95244,215.68816||255,0,0,255,239.23363,199.41858||255,0,0,255,249.8247,192.4459||255,0,0,255,261.35028,186.86777||255,0,0,255,261.9733,186.86777||255,0,0,255,261.9733,186.86777||255,0,0,255,50.77485,53.92204||255,0,0,255,50.77485,53.92204||255,0,0,255,50.77485,53.92204||255,0,0,255,50.77485,53.92204||255,0,0,255,48.905834,62.7541||255,0,0,255,39.56077,133.87541||255,0,0,255,44.856304,185.93808||255,0,0,255,53.578365,266.82114||255,0,0,255,53.578365,287.27435||255,0,0,255,51.70935,301.6845||255,0,0,255,51.39785,303.07904||255,0,0,255,51.086346,303.5439||255,0,0,255,51.086346,303.5439||255,0,0,255,90.02411,362.57922||255,0,0,255,88.155106,355.14172||255,0,0,255,109.02575,317.0244||255,0,0,255,133.01141,323.53226||255,0,0,255,155.43958,340.26666||255,0,0,255,166.65363,344.91513||255,0,0,255,185.03226,338.4073||255,0,0,255,193.13133,326.78616||255,0,0,255,210.26395,292.38763||255,0,0,255,228.01956,296.10638||255,0,0,255,259.7928,283.09073||255,0,0,255,266.33432,263.5672||255,0,0,255,267.58032,258.91876||255,0,0,255,269.76086,256.1297||255,0,0,255,271.94138,255.20001||255,0,0,255,284.71295,248.22733||255,0,0,255,294.3695,232.42259||255,0,0,255,297.48453,212.8991||255,0,0,255,297.48453,212.8991||255,0,0,255,101.86119,202.67252||255,0,0,255,101.86119,202.67252||255,0,0,255,101.86119,202.67252||255,0,0,255,113.07527,194.77013||255,0,0,255,141.73346,178.9654||255,0,0,255,144.8485,179.43024||255,0,0,255,166.96513,192.4459||255,0,0,255,170.70317,195.23497||255,0,0,255,193.75432,195.69983||255,0,0,255,201.85338,185.93808||255,0,0,255,212.75597,146.42624||255,0,0,255,217.4285,136.19965||255,0,0,255,231.44609,135.26996||255,0,0,255,241.41415,136.66449||255,0,0,255,250.13622,136.19965||255,0,0,255,279.41742,128.76212||255,0,0,255,312.12512,100.406555||255,0,0,255,312.12512,100.406555||255,0,0,255,92.20462,52.527508||255,0,0,255,92.20462,52.527508||255,0,0,255,159.48909,44.160294||255,0,0,255,186.90128,34.398544||255,0,0,255,242.97165,20.918034||255,0,0,255,269.13785,13.48051||255,0,0,255,288.76245,11.62113||255,0,0,255,288.76245,11.62113,";
StringTokenizer tokens = new StringTokenizer(parseStr, "||");
while(tokens.hasMoreTokens())
{
String second = tokens.nextToken();
StringTokenizer tempTokens = new StringTokenizer(second, ",");
int index = 0;
while(tempTokens.hasMoreTokens())
{
String splitStr = tempTokens.nextToken();
switch (index%6) {
case 0:
rArray.add(splitStr);
break;
case 1:
gArray.add(splitStr);
break;
case 2:
bArray.add(splitStr);
break;
case 3:
alphaArray.add(splitStr);
break;
case 4:
xPointArray.add(splitStr);
break;
case 5:
yPointArray.add(splitStr);
break;
default:
break;
}
index++;
Log.v("String44"," value = "+splitStr);
}
}
m.redraw();
}
public void colorChanged(int color) {
mPaint.setColor(color);
//method to convert integer color to r g b a
b = (color)&0xFF;
g = (color>>8)&0xFF;
r = (color>>16)&0xFF;
a = Math.round(((color>>>24)/255)*10);
}
public class MyView extends View {
private Bitmap mBitmap;
private Canvas mCanvas;
public Path mPath;
public Paint mBitmapPaint;
public MyView(Context c) {
super(c);
// reading screen size (for device Independence)
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
mBitmap = Bitmap.createBitmap(displaymetrics.widthPixels,displaymetrics.heightPixels, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
//background -- White
canvas.drawColor(0xFFFFFFFF);
//draw the bitmap from 0,0 the firstpoint in device's screen
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
public void touch_start(float x, float y) {
//reset touch so that a new path is to be drawn
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
public void touch_move(float x, float y) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
//point tracing
tracePoints((int)x, (int)y,(int)mX,(int)mY);
mX = x;
mY = y;
}
public void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
public void arrayPopulate(float atx,float aty){
if(eraseFlag==false){
//entering points into arrayLists
xPointArray.add(""+atx);
yPointArray.add(""+aty);
//add color as well
alphaArray.add(""+a);
rArray.add(""+r);
gArray.add(""+g);
bArray.add(""+b);
// if(toSend==null){
// toSend=""+r+","+g+","+b+","+a+","+atx+","+aty+"||";
// }
// else{
// toSend+=""+r+","+g+","+b+","+a+","+atx+","+aty+"||";
// }
//add data to a queue for sending to server
// Log.v("touch", toSend);
//send data here to server
//eraseFlag is true ends
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
arrayPopulate(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
arrayPopulate(x, y);
invalidate();
break;
}
return true;
}
public void redraw() {
int arraysize = FingerPaint.rArray.size();
int index=0;
float xx,yy;
//setting properties of tPaint
Paint tPaint= new Paint();
tPaint.setAntiAlias(true);
tPaint.setDither(true);
tPaint.setStyle(Paint.Style.STROKE);
tPaint.setStrokeJoin(Paint.Join.ROUND);
tPaint.setStrokeCap(Paint.Cap.ROUND);
tPaint.setColor(-16777216);
tPaint.setStrokeWidth(12);
while(index<arraysize){
//tPaint.setARGB(Integer.parseInt(alphaArray.get(0)), Integer.parseInt(rArray.get(0)), Integer.parseInt(gArray.get(0)), Integer.parseInt(bArray.get(0)));
//tPaint.setColor(Color.argb(Integer.parseInt(alphaArray.get(0)), Integer.parseInt(rArray.get(0)), Integer.parseInt(gArray.get(0)), Integer.parseInt(bArray.get(0))));
xx=Float.parseFloat(xPointArray.get(index));
yy=Float.parseFloat(yPointArray.get(index));
m.mCanvas.drawPoint(xx,yy,tPaint);
m.invalidate();
index++;
Log.d("__REDRAW__", "X="+xx+" Y="+yy);
}
}
}
//creating Options Menu - Inflater
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
//Option Menu Selection - Actions
@Override
public boolean onOptionsItemSelected(MenuItem item) {
mPaint.setXfermode(null);
mPaint.setAlpha(255);
switch (item.getItemId()) {
case R.id.COLOR:
this.eraseFlag=false;
new ColorPickerDialog(this, this, mPaint.getColor()).show();
return true;
case R.id.EMBOSS:
this.eraseFlag=false;
if (mPaint.getMaskFilter() != mEmboss) {
mPaint.setMaskFilter(mEmboss);
} else {
mPaint.setMaskFilter(null);
}
return true;
case R.id.BLUR:
this.eraseFlag=false;
if (mPaint.getMaskFilter() != mBlur) {
mPaint.setMaskFilter(mBlur);
} else {
mPaint.setMaskFilter(null);
}
return true;
case R.id.ERASE:
//for toggle detection
this.eraseFlag=true;
//reset blurr & Emboss
mPaint.setMaskFilter(null);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
return true;
case R.id.REDRAW:
this.eraseFlag=false;
//redraw the drawn points
m.redraw();
return true;
}
return super.onOptionsItemSelected(item);
}
//Bressenham's mid-point algorithm for finding all points between any two points --- Straight line
public void tracePoints(int xxx,int yyy,int x2, int y2) {
int w = x2 - xxx ;
int h = y2 - yyy ;
int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0 ;
if (w<0) dx1 = -1 ; else if (w>0) dx1 = 1 ;
if (h<0) dy1 = -1 ; else if (h>0) dy1 = 1 ;
if (w<0) dx2 = -1 ; else if (w>0) dx2 = 1 ;
int longest = Math.abs(w) ;
int shortest = Math.abs(h) ;
if (!(longest>shortest)) {
longest = Math.abs(h) ;
shortest = Math.abs(w) ;
if (h<0) dy2 = -1 ; else if (h>0) dy2 = 1 ;
dx2 = 0 ;
}
int numerator = longest >> 1 ;
for (int i=0;i<=longest;i++) {
m.arrayPopulate((float)xxx,(float)yyy) ;
numerator += shortest ;
if (!(numerator<longest)) {
numerator -= longest ;
xxx += dx1 ;
yyy += dy1 ;
} else {
xxx += dx2 ;
yyy += dy2 ;
}
}
}
}
答案 0 :(得分:1)
尝试以下代码。我希望它能解决你的问题。当我画画的时候,无论我是画得还是画得很快,我都能得到所有的分数。
public class HRCanvas extends Activity implements OnTouchListener{
DrawPanel dp;
private ArrayList<Path> pointsToDraw = new ArrayList<Path>();
private Paint mPaint;
Path path;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
dp = new DrawPanel(this);
dp.setOnTouchListener(this);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(30);
FrameLayout fl = new FrameLayout(this);
fl.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
fl.addView(dp);
setContentView(fl);
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
dp.pause();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
dp.resume();
}
public class DrawPanel extends SurfaceView implements Runnable{
Thread t = null;
SurfaceHolder holder;
boolean isItOk = false ;
public DrawPanel(Context context) {
super(context);
// TODO Auto-generated constructor stub
holder = getHolder();
}
@Override
public void run() {
// TODO Auto-generated method stub
while( isItOk == true){
if(!holder.getSurface().isValid()){
continue;
}
Canvas c = holder.lockCanvas();
c.drawARGB(255, 0, 0, 0);
onDraw(c);
holder.unlockCanvasAndPost(c);
}
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
synchronized(pointsToDraw)
{
for (Path path : pointsToDraw) {
canvas.drawPath(path, mPaint);
}
}
}
public void pause(){
isItOk = false;
while(true){
try{
t.join();
}catch(InterruptedException e){
e.printStackTrace();
}
break;
}
t = null;
}
public void resume(){
isItOk = true;
t = new Thread(this);
t.start();
}
}
@Override
public boolean onTouch(View v, MotionEvent me) {
// TODO Auto-generated method stub
synchronized(pointsToDraw)
{
if(me.getAction() == MotionEvent.ACTION_DOWN){
path = new Path();
path.moveTo(me.getX(), me.getY());
//path.lineTo(me.getX(), me.getY());
pointsToDraw.add(path);
}else if(me.getAction() == MotionEvent.ACTION_MOVE){
path.lineTo(me.getX(), me.getY());
}else if(me.getAction() == MotionEvent.ACTION_UP){
//path.lineTo(me.getX(), me.getY());
}
}
return true;
}
}
答案 1 :(得分:1)
您需要进行插值以查找更新之间的点。我推荐余弦插值。它易于实现,产生不错的结果,并且计算成本低廉。
public double cosineInterpolation(double x1, double x2, double normal)
{
double ft = normal * 3.1415927;
double f = (1 - Math.cos(ft)) * .5;
return x1 * (1 - f) + x2 * f;
}
你需要两次调用此方法;一次用于x,一次用于两个后续点的y坐标。
答案 2 :(得分:0)
你可以用MATH方程来解决这个问题。
使用线方程,y = mx + c 将(x1,y1)和(x2,y2)放到两个方程中求解得到m和c的值。 (你将能够找到直接方程式来获得m和c)。 然后创建一个从x = x1开始直到x = x2的循环 使用y = mx + c,得到y的值(现在你知道m和c)
我希望这是有帮助的。
答案 3 :(得分:0)
为触摸事件替换此代码....
float downx = 0;
float downy = 0;
float upx = 0;
float upy = 0;
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
downx = event.getX();
downy = event.getY();
break;
case MotionEvent.ACTION_MOVE:
upx = event.getX();
upy = event.getY();
canvas.drawLine(downx, downy, upx, upy, paint);
imageView.invalidate();
downx = upx;
downy = upy;
break;
break;
case MotionEvent.ACTION_UP:
upx = event.getX();
upy = event.getY();
canvas.drawLine(downx, downy, upx, upy, paint);
imageView.invalidate();
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
return true;
}
答案 4 :(得分:0)
查看此code。该项目尚未完成,但我的Atrix上的线条快速而顺畅。虽然它确实使用quadTo听起来像你想要避免。你正在测试什么设备?
答案 5 :(得分:0)
我注意到您未在arrayPopulate(x, y);
案例下的onTouchEvent(MotionEvent event)
函数中调用MotionEvent.ACTION_MOVE
。你很可能在那里丢失数据吗?
你有什么理由试图重新编码Path类吗?如果您真的需要,您可能必须包括bezier曲线和直线以及更多,如果您决定使用其中的任何other functions。如果他们使用原生的bezier曲线,那么你可能也想要。
答案 6 :(得分:0)
我面临与AndroidKid相同的问题,
由于后台操作的数量,我的应用程序无法记录触摸事件的所有点。我的测试应用程序捕获了一个动作的二十个位置,而我的实际应用程序只捕获了5到6个点。所以我得到像对象一样的多边形作为结果。
正如Android Kid所说,当我慢慢画画时,我会得到正确的曲线,因为正确记录了这些点。
在我的测试应用中,我有一个路径对象来追加点并使用canvas.drawPath
,这比canvas.drawLine
给出了更好的结果。
Android Kid,
如果您可以使用路径中的平滑曲线来破坏锋利边缘,请尝试此操作。
paint.setPathEffect(new CornerPathEffect(25));
无论如何,会让你们发帖!!
答案 7 :(得分:0)
我知道这个问题已经过时,但是可以获取事件中的所有要点,此时硬件跟踪事件的速度快于使用事件历史记录传递的事件。类似的东西:
int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++) {
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
path.lineTo(historicalX, historicalY);
}
答案 8 :(得分:-1)
为什么不用黑色将其绘制到位图上,然后循环遍历所有像素以获得点?
Paint cPaint = new Paint();
cPaint.setAntiAlias(false);
cPaint.setColor(0xFF000000);
Bitmap topBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas topCanvas = new Canvas(topBitmap);
topCanvas.drawColor(0xFFFFFFFF, PorterDuff.Mode.CLEAR);
topCanvas.drawPath(mPath, cPaint);
for (int x=0; x<w; x++) {
for (int y=0; y<h; y++) {
if (topBitmap.getPixel(x, y) == 0xFF000000) {
// record the point
}
}
}
在任何情况下,路径都不会包含绘制的每个点。此外,如果其他设备也在运行android或具有类似于路径对象的东西,则可以使用运动事件中的点重新创建路径。