I can create circle on touch but can not remove the previous one. I have manage to remove the very first circle but the code is poor and it does not really work as I want. I like to draw circle every time I touch the screen and remove the previous circle . So the screen starts with a circle and as I will touch a new position the previous should be removed and there will be a new one.So how to do that part?
Here is my work:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Display display = new Display(this);
display.init();
display.backPaint.setColor(Color.WHITE);
setContentView(display);
}
static class Display extends View {
ArrayList<Point> points = new ArrayList();
int touch1_x=700;
int touch1_y=700;
Paint backPaint;
Paint circlePaint;
Paint circlePaint2;
Display(Context context) {
super(context);
}
void init() {
backPaint = new Paint();
backPaint.setColor(Color.WHITE);
backPaint.setStyle(Paint.Style.FILL);
circlePaint = new Paint();
circlePaint.setColor(Color.YELLOW);
circlePaint2 = new Paint();
circlePaint2.setColor(Color.WHITE);
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getActionMasked()) {
// if (event.getX(event.getActionIndex()) > 100 && event.getX(event.getActionIndex()) < 200) {
touch1_x = (int) event.getX(event.getActionIndex());
touch1_y = (int) event.getY(event.getActionIndex());
// }
System.out.println("touch1_x ===" + touch1_x);
points.add(new Point(touch1_x, touch1_y));
points.add(new Point(touch1_x, touch1_y));
return true;
}
return false;
}
});
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, getWidth(), getHeight(), backPaint);
canvas.drawCircle(touch1_x, touch1_y, 50, circlePaint);
for(Point p: points){
canvas.drawCircle(p.x, p.y, 50, circlePaint);
}
for(Point p: points){
canvas.drawCircle(p.x, p.y, 50,circlePaint2 );
}
invalidate();
}
}
}
relevant question
You could erase canvas before drawing the next circle, using
canvas.drawColor(Color.TRANSPARENT,Mode.CLEAR);
import turtle
t=turtle.Turtle()
wn=turtle.Screen()
for count in range(360):
t.fd(3)
t.rt(1)
wn.exitonclick()
I have a customised view for photo annotate, you can use this to do your job.
1: Create a file AnnotationView.java and copy the following code
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
/**
* #author Bob Gao
* http://bobgao.net
*/
public class AnnotationView extends ImageView implements OnTouchListener {
private static final float KEY_STROKE_WIDTH = 4;
private List<Annotation> annotations = new ArrayList<Annotation>();
private Annotation mAnnotation;
private Canvas mCanvas;
private Paint mPaint;
// private Rect mOutRect;
public AnnotationView(Context context) {
super(context);
setOnTouchListener(this);
setDrawingCacheEnabled(true);
setScaleType(ScaleType.FIT_XY);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.mCanvas = canvas;
for (Annotation annotation : annotations) {
mPaint.setColor(annotation.getColor());
switch (annotation.getShape()) {
case Annotation.KEY_SHAPE_CIRCLE:
drawCircle(annotation.getX(), annotation.getY(), annotation.getRadius());
break;
case Annotation.KEY_SHAPE_ARROW:
drawAL((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius(), annotation.getDegree());
break;
case Annotation.KEY_SHAPE_SQUARES:
drawRect((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius());
break;
case Annotation.KEY_SHAPE_TRIANGLE:
drawTriangle((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius(), annotation.getDegree());
break;
}
}
}
/**
* Draw a triangle
*
* #param x
* #param y
* #param r
*/
public void drawTriangle(int x, int y, int r, float degree) {
Path path = new Path();
path.moveTo(x, y);
path.lineTo(x - 2 * r, y + 2 * r);
path.lineTo(x + 2 * r, y + 2 * r);
path.lineTo(x, y);
path.close();
rotatePath(path, degree);
mCanvas.drawPath(path, mPaint);
}
public void drawRect(int x, int y, int r) {
int lenght = 4 * r;
int left = x - lenght / 2;
int top = y - lenght / 2;
int right = x + lenght / 2;
int bottom = y + lenght / 2;
Path path = new Path();
path.moveTo(left, top);
path.lineTo(right, top);
path.lineTo(right, bottom);
path.lineTo(left, bottom);
path.lineTo(left, top);
path.close();
mCanvas.drawPath(path, mPaint);
}
public void drawCircle(float x, float y, float r) {
mCanvas.drawCircle(x, y, r, mPaint);
}
/**
* Draw arrow
*
* #param sx
* #param sy
* #param ex
* #param ey
*/
public void drawAL(int sx, int sy, int r, float degree) {
int ex = (int) (sx + 2 * r);
int ey = (int) (sy + 2 * r);
switch (new Float(degree).intValue()) {
case 90:
ex = (int) (sx - 2 * r);
ey = (int) (sy + 2 * r);
break;
case 180:
ex = (int) (sx - 2 * r);
ey = (int) (sy - 2 * r);
break;
case 270:
ex = (int) (sx + 2 * r);
ey = (int) (sy - 2 * r);
break;
}
double H = 8; // the height of arrow
double L = 3.5; // half of bottom line
int x3 = 0;
int y3 = 0;
int x4 = 0;
int y4 = 0;
double awrad = Math.atan(L / H); // the rotation of arrow
double arraow_len = Math.sqrt(L * L + H * H); // the length of arrow
double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
double x_3 = ex - arrXY_1[0]; // (x3,y3) the first point
double y_3 = ey - arrXY_1[1];
double x_4 = ex - arrXY_2[0]; // (x4,y4) the second point
double y_4 = ey - arrXY_2[1];
Double X3 = new Double(x_3);
x3 = X3.intValue();
Double Y3 = new Double(y_3);
y3 = Y3.intValue();
Double X4 = new Double(x_4);
x4 = X4.intValue();
Double Y4 = new Double(y_4);
y4 = Y4.intValue();
// draw line
mCanvas.drawLine(sx, sy, ex, ey, mPaint);
Path triangle = new Path();
triangle.moveTo(ex, ey);
triangle.lineTo(x3, y3);
triangle.lineTo(x4, y4);
triangle.close();
mCanvas.drawPath(triangle, mPaint);
}
// Calculate
public double[] rotateVec(int px, int py, double ang, boolean isChLen, double newLen) {
double mathstr[] = new double[2];
// 矢量旋转函数,参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度
double vx = px * Math.cos(ang) - py * Math.sin(ang);
double vy = px * Math.sin(ang) + py * Math.cos(ang);
if (isChLen) {
double d = Math.sqrt(vx * vx + vy * vy);
vx = vx / d * newLen;
vy = vy / d * newLen;
mathstr[0] = vx;
mathstr[1] = vy;
}
return mathstr;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
if (mAnnotation != null) {
float minX = 0;
float minY = 0;
float maxX = 0;
float maxY = 0;
switch (mAnnotation.getShape()) {
case Annotation.KEY_SHAPE_ARROW:
minX = 0;
minY = 0;
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
break;
case Annotation.KEY_SHAPE_SQUARES:
minX = getLeft() + mAnnotation.getRadius() / 2;
minY = getTop() + mAnnotation.getRadius() / 2;
maxX = getLeft() + getWidth() - mAnnotation.getRadius() / 2;
maxY = getTop() + getHeight() - mAnnotation.getRadius() / 2;
break;
case Annotation.KEY_SHAPE_CIRCLE:
minX = 0;
minY = 0;
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
case Annotation.KEY_SHAPE_TRIANGLE:
minX = getLeft() + mAnnotation.getRadius();
minY = getTop() + mAnnotation.getRadius();
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
break;
}
if (x > minX && x < maxX && y > minY && y < maxY) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mAnnotation.setX(x);
mAnnotation.setY(y);
postInvalidate();
case MotionEvent.ACTION_MOVE:
mAnnotation.setX(x);
mAnnotation.setY(y);
postInvalidate();
break;
}
}
return true;
}
return false;
}
public void startAnnotate(String pathName) {
mAnnotation = new Annotation();
mAnnotation.setMaxRadius(getWidth() / 2);
mAnnotation.setColor(Color.RED);
mAnnotation.setX(getWidth() / 2);
mAnnotation.setY(getHeight() / 2);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(KEY_STROKE_WIDTH);
annotations.add(mAnnotation);
postInvalidate();
}
public void stopAnnotate() {
if (annotations.isEmpty()) {
mPaint = null;
mAnnotation = null;
} else {
annotations.remove(annotations.size() - 1);
if (annotations.isEmpty()) {
mAnnotation = null;
mPaint = null;
} else {
mAnnotation = annotations.get(annotations.size() - 1);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mAnnotation.getColor());
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(KEY_STROKE_WIDTH);
}
}
postInvalidate();
}
public void plus() {
if (mAnnotation != null) {
mAnnotation.plus();
postInvalidate();
}
}
public void sub() {
if (mAnnotation != null) {
mAnnotation.sub();
postInvalidate();
}
}
public void rotateRight() {
if (mAnnotation != null) {
if (mAnnotation.getDegree() >= 360) {
mAnnotation.setDegree(0);
} else {
mAnnotation.setDegree(mAnnotation.getDegree() + 90);
}
postInvalidate();
}
}
public void rotateLeft() {
if (mAnnotation != null) {
if (mAnnotation.getDegree() <= 0) {
mAnnotation.setDegree(270);
} else {
mAnnotation.setDegree(mAnnotation.getDegree() - 90);
}
postInvalidate();
}
}
public void changeColor(int color) {
if (mAnnotation != null) {
mAnnotation.setColor(color);
mPaint.setColor(color);
}
postInvalidate();
}
/**
* Change the shape
*
* #param id
*/
public void changeShape(int id) {
if (mAnnotation != null) {
mAnnotation.setShape(id);
postInvalidate();
}
}
/**
* Draw line
*
* #param fromX
* start point x
* #param fromY
* start point y
* #param toX
* end point x
* #param toY
* end point y
*/
public void drawLine(float fromX, float fromY, float toX, float toY) {
Path linePath = new Path();
linePath.moveTo(fromX, fromY);
linePath.lineTo(toX, toY);
linePath.close();
mCanvas.drawPath(linePath, mPaint);
invalidate();
}
public List<Annotation> getAnnotations() {
return annotations;
}
private void rotatePath(Path path, float degree) {
Matrix mMatrix = new Matrix();
RectF bounds = new RectF();
path.computeBounds(bounds, true);
mMatrix.postRotate(degree, (bounds.right + bounds.left) / 2, (bounds.bottom + bounds.top) / 2);
path.transform(mMatrix);
}
}
2. In your activity, create the AnnotationView and assign your image to it, then append this view to your root view.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AnnotationView mPreview = (FrameLayout) findViewById(R.id.camera_preview);
AnnotationView mAnnotationView = new AnnotationView(this);
Bitmap bitmap;
try {
bitmap = CBitmapUtil.decode(mPictureFile); // Get your image as a bitmap
mAnnotationView.setImageBitmap(bitmap);
mPreview.addView(mAnnotationView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(this, "Photo cannot be saved, please try again later.", Toast.LENGTH_SHORT).show();
}
}
Related
I'm learning 3D rendering with java and I encountered a weird issue.
I'm able to rotate and display 3D objects to the screen. but when I tried to use prospective projection to show depth, the program freaks out. No errors or anything, but the depth seems to stretch incurability long. I narrowed the problem down to the perspective divide in the projection function.
Can anyone help?
public class Renderer extends JPanel{
public Renderer() {
}
double angle = 0;
double a;
double f;
double l;
double offSet;
public void update() {
angle += 0.03;
repaint();
}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
super.paintComponent(g2d);
for(Triangle element: MidService.mesh)
{
Vertex v1 = rotateY(element.v1);
Vertex v2 = rotateY(element.v2);
Vertex v3 = rotateY(element.v3);
v1 = projection(v1);
v2 = projection(v2);
v3 = projection(v3);
int offSet = (int) (MidService.displayX/2);
g2d.drawLine(offSet + v1.x, offSet + v1.y, offSet + v2.x, offSet + v2.y);
g2d.drawLine(offSet + v2.x, offSet + v2.y, offSet + v3.x, offSet + v3.y);
g2d.drawLine(offSet + v3.x, offSet + v3.y, offSet + v1.x, offSet + v1.y);
}
}
public Vertex projection(Vertex v)
{
a = MidService.displayY / MidService.displayX;
f = 1 / (Math.tan(MidService.fieldOfView/2));
l = MidService.Zfar / (MidService.Zfar - MidService.Znear);
offSet = MidService.Zfar / (MidService.Zfar - MidService.Znear) * MidService.Znear;
double x = (v.x * a * f);
double y = (v.y * f);
double z = (v.z * l - offSet);
double w = v.z;
//the if function below caused the issue
if(w != 0.0) {
x /= w;
y /= w;
z /= w;
}
return new Vertex((int)x, (int)y, (int)z);
}
public Vertex rotateY(Vertex v)
{
double x = v.x * Math.cos(angle) + v.z * Math.sin(angle);
double y = v.y;
double z = v.x * (-Math.sin(angle)) + v.z * Math.cos(angle);
return new Vertex((int)x, (int)y, (int)z);
}
//-------------------------------------------------------
public class MidService {
public static double displayX = 1000;
public static double displayY = 1000;
public static double fieldOfView = 180;
public static double Zfar = 10;
public static double Znear = 1;
public static ArrayList<Triangle> mesh = new ArrayList<>();
}
//---------------------------------------------
public class Driver {
public static void main(String[] args) {
Display display = new Display();
MidService.mesh.add(new Triangle(new Vertex(-100, 100, 100),
new Vertex(-100, -100, 100),
new Vertex(100, -100, 100)));
MidService.mesh.add(new Triangle(new Vertex(-100, 100, 100),
new Vertex(100, -100, 100),
new Vertex(100, 100, 100)));
Here's a video of it:[https://youtu.be/bFJLU5c3JE0]
A follow up to the perspective division issue. It turns out to be the inverse of the difference between camera distance and z coordinate. So instead of division by z, its 1/(distance - z)
Below is modification for Gaba Miau's matrix multiply function
Vertex Mult(float[][] mat,Vertex v){
float ver[] = {v.x,v.y,v.z,v.w};
float ans[] = {0,0,0,0};
for (int i=0;i<mat.length;i++){
for(int j=0;j<mat[0].length;j++){
ans[i] += mat[i][j] * ver[j];
}
}
float temp = 100/(500 - v.z);
if(temp != 0)
{
ans[0] *= temp;
ans[1] *= temp;
ans[2] *= temp;
}
Vertex vans = new Vertex((int)ans[0],(int)ans[1],(int)ans[2]);
vans.w =(int) ans[3];
return vans;
}
P.S. it's ans[i] += mat[i][j] * ver[j]; in the forloop
Firstly you should be using a graphics API like OpenGL or DirectX, secondly you should be using a math library like GLM that contains all the projection matrix formulas and other stuff. Thirdly, you shouldn't be using int as a datatype to store vertex data.
I made a few changes to your code so it doesn't freak out anymore.
The fov should be in the range(0.001,179.999), never 180, it is recommanded using 90 deg. Also the math function tan takes in radians not deg.
package Render;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.sound.midi.MidiDevice;
import javax.swing.JPanel;
import Beans.Triangle;
import Beans.Vertex;
import Utilities.MidService;
public class Renderer extends JPanel{
public Renderer() {
}
double angle = 0;
double a;
double f;
double l;
double offSet;
public void update() {
//angle += 0.03;
repaint();
}
float projMat[][]= {
{1f / ((float)Math.tan(MidService.fieldOfView/2f)),0,0,0},
{0,1f / ((float)Math.tan(MidService.fieldOfView/2f)),0,0},
{0,0,MidService.Zfar / (MidService.Zfar - MidService.Znear),1},
{0,0,-MidService.Zfar* MidService.Znear / (MidService.Zfar - MidService.Znear),0},
};
Vertex Mult(float[][] mat,Vertex v){
float ver[] = {v.x,v.y,v.z,v.w};
float ans[] = {0,0,0,0};
for (int i=0;i<mat.length;i++){
for(int j=0;j<mat[0].length;j++){
ans[i] += mat[i][j] * ver[i];
}
}
Vertex vans = new Vertex((int)ans[0],(int)ans[1],(int)ans[2]);
vans.w =(int) ans[3];
return vans;
}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
super.paintComponent(g2d);
for(Triangle element: MidService.mesh)
{
Vertex v1 = rotateZ(element.v1);
Vertex v2 = rotateZ(element.v2);
Vertex v3 = rotateZ(element.v3);
v1 = rotateY(v1);
v2 = rotateY(v2);
v3 = rotateY(v3);
v1 = Mult(projMat,v1);
v2 = Mult(projMat,v2);
v3 = Mult(projMat,v3);
int offSet = (int) (MidService.displayX/2);
g2d.drawLine(offSet + (int)v1.x, offSet + (int)v1.y, offSet + (int)v2.x, offSet + (int)v2.y);
g2d.drawLine(offSet + (int)v2.x, offSet + (int)v2.y, offSet + (int)v3.x, offSet + (int)v3.y);
g2d.drawLine(offSet + (int)v3.x, offSet + (int)v3.y, offSet + (int)v1.x, offSet + (int)v1.y);
}
}
public Vertex projection(Vertex v)
{
a = MidService.displayY / MidService.displayX;
f = 1 / (Math.tan(MidService.fieldOfView/2));
l = MidService.Zfar / (MidService.Zfar - MidService.Znear);
offSet = MidService.Zfar / (MidService.Zfar - MidService.Znear) * MidService.Znear;
double x = (v.x * a * f);
double y = (v.y * f);
double z = (v.z * l - offSet);
double w = v.z;
if(w != 0.0) {
x /= w;
y /= w;
z /= w;
}
return new Vertex((int)x, (int)y, (int)z);
}
public Vertex rotateY(Vertex v)
{
double x = v.x * Math.cos(angle) + v.z * Math.sin(angle);
double y = v.y;
double z = v.x * (-Math.sin(angle)) + v.z * Math.cos(angle);
return new Vertex((int)x, (int)y, (int)z);
}
public Vertex rotateZ(Vertex v)
{
double x = v.x * Math.cos(angle) + v.y * (-Math.sin(angle));
double y = v.x * Math.sin(angle) + v.y * Math.cos(angle);
double z = v.z;
return new Vertex((int)x, (int)y, (int)z);
}
}
Here is the MidService class
package Utilities;
import java.util.ArrayList;
import Beans.Triangle;
public class MidService {
public static float displayX = 1000;
public static float displayY = 1000f;
public static float fieldOfView = 3.14f/2f;
public static float Zfar = 100f;
public static float Znear = 0.1f;
public static ArrayList<Triangle> mesh = new ArrayList<>();
}
And Vertex
package Beans;
public class Vertex {
public float x;
public float y;
public float z;
public float w = 1;
public Vertex(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
}
I have a problem.
How do I check if path in Android intersect with itself?
I have this class:
public class GameView extends SurfaceView implements Runnable {
Thread gameThread = null;
SurfaceHolder surfaceHolder;
volatile boolean playing;
Canvas canvas;
private final static int MAX_FPS = 60;
private final static int FRAME_PERIOD = 1000 / MAX_FPS;
ArrayList<Point> points = new ArrayList<>();
private Context ctx;
Path path;
public static final int DEFAULT_COLOR = Color.RED;
public static final int DEFAULT_BG_COLOR = Color.WHITE;
private static final float TOUCH_TOLERANCE = 4;
private float mX, mY;
private Path mPath;
private Paint mPaint;
private int backgroundColor = DEFAULT_BG_COLOR;
public GameView(Context context) {
super(context);
ctx = context;
surfaceHolder = getHolder();
surfaceHolder.setFormat(PixelFormat.RGBA_8888);
path = new Path();
playing = true;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(DEFAULT_COLOR);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setXfermode(null);
mPaint.setAlpha(0xff);
mPaint.setStrokeWidth(12);
}
static Boolean isPathComplex(List<Point> path) {
if (path == null || path.size() <= 2) {
return false;
}
int len = path.size();
for (int i = 1; i < len; i++) {
Point lineAStart = path.get(i - 1);
Point lineAEnd = path.get(i);
for (int j = i + 1; j < len; j++) {
Point lineBStart = path.get(j - 1);
Point lineBEnd = path.get(j);
if (lineSegmentsIntersect(lineAStart.x,lineAStart.y,
lineAEnd.x,lineAEnd.y,
lineBStart.x,lineBStart.y,
lineBEnd.x,lineBEnd.y)) {
return true;
}
} // inner loop
} // outer loop
return false;
}
static Boolean lineSegmentsIntersect(float p0_x, float p0_y, float p1_x, float p1_y,
float p2_x, float p2_y, float p3_x, float p3_y) {
float s1_x, s1_y, s2_x, s2_y;
s1_x = p1_x - p0_x; s1_y = p1_y - p0_y;
s2_x = p3_x - p2_x; s2_y = p3_y - p2_y;
float s, t;
s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
{
// Collision detected
return true;
}
return false; // No collision
}
public void update(){
isPathComplex(points);
}
public void draw(){
if(surfaceHolder.getSurface().isValid()){
canvas = surfaceHolder.lockCanvas();
if(canvas != null) {
canvas.drawColor(backgroundColor);
if (mPath != null) {
canvas.drawPath(mPath, mPaint);
}
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
#Override
public void run() {
while(playing){
long started = System.currentTimeMillis();
float deltaTime = (System.currentTimeMillis() - started);
int sleepTime = (int) (FRAME_PERIOD - deltaTime);
update();
draw();
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime);
}
catch (InterruptedException e) {
}
}
while (sleepTime < 0) {
update();
draw();
sleepTime += FRAME_PERIOD;
}
}
}
private void touchStart(float x, float y) {
mPath = new Path();
points.add(new Point((int)x,(int)y));
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touchMove(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
points.add(new Point((int)x,(int)y));
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touchUp() {
mPath.lineTo(mX, mY);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN :
touchStart(x, y);
break;
case MotionEvent.ACTION_MOVE :
touchMove(x, y);
break;
case MotionEvent.ACTION_UP :
touchUp();
break;
}
return true;
}
public void pause() {
playing = false;
try {
gameThread.join();
} catch (InterruptedException e) {
Log.e("Error:", "joining thread");
}
}
public void resume(Context context) {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
}
Please do you know some solution for this problem?
I tried a lot but nothing helped me with my problem.
What I want to achieve is to detect intersect like this
I tried solution with points from Check android.graphics.path intersection with itself but it seems not to be working for me.
I could also be doing something wrong because i am newbie to android development and programming in general :) .
Thank you in advance!
Edit:
To detect intersect i followed above solution and modified this function https://stackoverflow.com/a/1968345/9339525 but It returns almost all the time true even if path is not crossing itself.
All code for detect intersection:
static Boolean isPathComplex(List<Point> path) {
if (path == null || path.size() <= 2) {
return false;
}
int len = path.size();
for (int i = 1; i < len; i++) {
Point lineAStart = path.get(i - 1);
Point lineAEnd = path.get(i);
for (int j = i + 1; j < len; j++) {
Point lineBStart = path.get(j - 1);
Point lineBEnd = path.get(j);
if (lineSegmentsIntersect(lineAStart.x,lineAStart.y,
lineAEnd.x,lineAEnd.y,
lineBStart.x,lineBStart.y,
lineBEnd.x,lineBEnd.y)) {
return true;
}
} // inner loop
} // outer loop
return false;
}
static Boolean lineSegmentsIntersect(float p0_x, float p0_y, float p1_x, float p1_y,
float p2_x, float p2_y, float p3_x, float p3_y) {
float s1_x, s1_y, s2_x, s2_y;
s1_x = p1_x - p0_x; s1_y = p1_y - p0_y;
s2_x = p3_x - p2_x; s2_y = p3_y - p2_y;
float s, t;
s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
// Collision detected
return true;
}
return false; // No collision
}
Edit:
I modified my class GameView and added method to detect intersection.
I could not stand that is was that difficult so i switched on the computer and coded something.
I tried only a few values and dont know what happens if begin-end points of segments coincide.
Please try out.
static boolean lineSegmentsDoIntersect(
float Ax, float Ay
, float Bx, float By
, float Cx, float Cy
, float Dx, float Dy) {
// two line segments: AB and CD
// segment AB intersects segment CD
// if A and B on different sides of line through C and D
// AND C and D on different sides of line through A and B
// note the difference between line and segment!
if ( ! pointsOnDifferentSidesOfLineThrough(Ax, Ay, Bx, By, Cx, Cy, Dx, Dy) )
return false;
if ( ! pointsOnDifferentSidesOfLineThrough(Cx, Cy, Dx, Dy, Ax, Ay, Bx, By) )
return false;
return true;
}
static boolean pointsOnDifferentSidesOfLineThrough(
float Ax, float Ay
, float Bx, float By
, float x1, float y1
, float x2, float y2) {
// determine equation of line through C and D
// y = ax + b
// a = (y2-y1)/(x2-x1) but.. ( x2-x1) not equal to zero
// y-y1 = a (x-x1)
// y = a (x-x1) + y1
// y = ax -ax1 + y1
// b = -ax1 + y1
//but.. (x2-x1) not 0
if ( x2==x1)
{
if ( Ax > x1 && Bx > x1 )
return false;
if ( Ax < x1 && Bx < x1 )
return false;
return true;
}
float a = (y2-y1)/(x2-x1);
float b = -a * x1 + y1;
float yA = a * Ax + b;
float yB = a * Bx + b;
if ( yA > Ay && yB > By )
return false;
if ( yA < Ay && yB < By )
return false;
return true;
}
This is my code to rotate the wheel and sound cordinator according to rotation but I want to rotate the wheel according to fix color on fix point.
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.RectF;
import android.media.MediaPlayer;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import com.spin.wheel.manager.MyDBAdapter;
import com.spin.wheel.manager.Prefs;
import com.spin.wheel.ui.activity.HomeActivity;
import java.util.List;
import java.util.Random;
public class WheelView extends View {
public boolean lifted;
private Paint circlePaint;
private long currTime;
private String item;
private Paint item10Paint;
private Paint item11Paint;
private Paint item12Paint;
private Paint item13Paint;
private Paint item14Paint;
private Paint item15Paint;
private Paint item1Paint;
private Paint item2Paint;
private Paint item3Paint;
private Paint item4Paint;
private Paint item5Paint;
private Paint item6Paint;
private Paint item7Paint;
private Paint item8Paint;
private Paint item9Paint;
private float itemLength;
private List<String> itemNames;
private double lastTheta;
private String listName;
private Paint markerPaint;
private long oldTime;
private Paint pointerPaint;
private int px;
WheelView wheelView;
private int py;
private float radius;
private MediaPlayer resourcePlayer;
private Paint rimPaint;
private double rotationOffset;
private int selected;
private Paint textPaint;
private boolean textSet;
private long timeDiff;
private Paint titlePaint;
private String winner;
int padding;
int center;
Context mContext;
public WheelView(Context context) {
super(context);
mContext=context;
initWheelView();
}
public WheelView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext=context;
initWheelView();
}
public WheelView(Context context, AttributeSet ats, int defaultStyle) {
super(context, ats, defaultStyle);
mContext=context;
initWheelView();
}
protected void initWheelView() {
setFocusable(true);
Resources r = getResources();
this.circlePaint = new Paint(1);
this.circlePaint.setColor(r.getColor(R.color.wheel_color));
this.circlePaint.setStrokeWidth(5.0f);
this.circlePaint.setStyle(Style.STROKE);
this.rimPaint = new Paint(1);
this.rimPaint.setColor(r.getColor(R.color.text_color));
this.rimPaint.setStrokeWidth(1.0f);
this.rimPaint.setStyle(Style.STROKE);
this.textPaint = new Paint(1);
this.textPaint.setColor(r.getColor(R.color.text_color));
this.titlePaint = new Paint(1);
this.titlePaint.setColor(r.getColor(R.color.text_color));
this.pointerPaint = new Paint(1);
this.pointerPaint.setColor(r.getColor(R.color.pointer_color));
this.markerPaint = new Paint(1);
this.markerPaint.setStrokeWidth(2.0f);
this.markerPaint.setColor(r.getColor(R.color.marker_color));
this.item1Paint = new Paint(1);
this.item1Paint.setColor(r.getColor(R.color.item1_color));
this.item2Paint = new Paint(1);
this.item2Paint.setColor(r.getColor(R.color.item2_color));
this.item3Paint = new Paint(1);
this.item3Paint.setColor(r.getColor(R.color.item3_color));
this.item4Paint = new Paint(1);
this.item4Paint.setColor(r.getColor(R.color.item4_color));
this.item5Paint = new Paint(1);
this.item5Paint.setColor(r.getColor(R.color.item5_color));
this.item6Paint = new Paint(1);
this.item6Paint.setColor(r.getColor(R.color.item6_color));
this.item7Paint = new Paint(1);
this.item7Paint.setColor(r.getColor(R.color.item7_color));
this.item8Paint = new Paint(1);
this.item8Paint.setColor(r.getColor(R.color.item8_color));
this.item9Paint = new Paint(1);
this.item9Paint.setColor(r.getColor(R.color.item9_color));
this.item10Paint = new Paint(1);
this.item10Paint.setColor(r.getColor(R.color.item10_color));
this.item11Paint = new Paint(1);
this.item11Paint.setColor(r.getColor(R.color.item11_color));
this.item12Paint = new Paint(1);
this.item12Paint.setColor(r.getColor(R.color.item12_color));
this.item13Paint = new Paint(1);
this.item13Paint.setColor(r.getColor(R.color.item13_color));
this.item14Paint = new Paint(1);
this.item14Paint.setColor(r.getColor(R.color.item14_color));
this.item15Paint = new Paint(1);
this.item15Paint.setColor(r.getColor(R.color.item15_color));
this.lifted = false;
this.selected = -1;
this.lastTheta = 0.0d;
this.timeDiff = 0;
this.oldTime = System.currentTimeMillis();
this.currTime = System.currentTimeMillis();
this.winner = "";
this.resourcePlayer = MediaPlayer.create(getContext(), R.raw.wheel_sound_new);
this.item = "";
this.itemLength = 0.0f;
this.listName = "";
this.textSet = false;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measure(widthMeasureSpec), measure(heightMeasureSpec));
int width = Math.min(getMeasuredWidth(), getMeasuredHeight());
padding = getPaddingLeft() == 0 ? 0 : getPaddingLeft();
radius = width - padding * 2;
center = width / 2;
}
private int measure(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == 0) {
return 200;
}
return specSize;
}
public boolean withinWheel(float _x, float _y) {
return getRadius() * getRadius() > ((_x - ((float) getPX())) * (_x - ((float) getPX()))) + ((((float) getPY()) - _y) * (((float) getPY()) - _y));
}
public void setList(String _listName) {
this.listName = _listName;
}
public void setRotation(double _rotation) {
Log.e("##_rotation", String.valueOf(_rotation));
this.rotationOffset = _rotation % 360.0d;
}
public double getRotationNumber() {
Log.e("##rotationOffset", String.valueOf(rotationOffset));
return this.rotationOffset;
}
public void setLastTheta(double _lastTheta, float width) {
float offset = 12800.0f / width;
if (_lastTheta < -40.0d) {
_lastTheta = (double) (-offset);
}
if (_lastTheta > 40.0d) {
_lastTheta = (double) offset;
}
this.lastTheta = _lastTheta;
}
public void setItems(List<String> items) {
this.itemNames = items;
}
public int getPX() {
return getMeasuredWidth() / 2;
}
public int getPY() {
return getMeasuredHeight() / 2;
}
public float getRadius() {
return ((float) Math.min(getPX(), getPY())) * 0.8f;
}
protected void onDraw(Canvas canvas) {
float tempAngle = 0;
float sweepAngle = 360 /6;
if (this.itemNames != null) {
int i;
float offSet = 0;
this.px = getMeasuredWidth() / 2;
this.py = getMeasuredHeight() / 2;
if (!this.textSet) {
this.textPaint.setTextSize((float) (getMeasuredWidth() / 25));
this.titlePaint.setTextSize((float) (getMeasuredWidth() / 15));
this.textSet = true;
}
this.radius = ((float) Math.min(this.px, this.py)) * 0.8f;
float incr = 360.0f / ((float) this.itemNames.size());
RectF myCircleBox = new RectF(((float) this.px) - this.radius, ((float) this.py) - this.radius, ((float) this.px) + this.radius, ((float) this.py) + this.radius);
RectF rectF = new RectF(((float) this.px) - (this.radius / 5.0f), ((float) this.py) - (this.radius * 1.1f), ((float) this.px) + (this.radius / 5.0f), ((float) this.py) - (this.radius * 0.6f));
rectF = new RectF((((float) this.px) - (this.radius / 5.0f)) + 5.0f, (((float) this.py) - (this.radius * 1.1f)) + 2.0f, (((float) this.px) + (this.radius / 5.0f)) - 5.0f, (((float) this.py) - (this.radius * 0.6f)) - 12.0f);
Log.e("##rotationOffset", String.valueOf(rotationOffset));
double actualRotation = this.rotationOffset + ((double) ((incr / 2.0f) + 90.0f));
canvas.save();
canvas.rotate((float) this.rotationOffset, (float) this.px, (float) this.py);
for (i = 0; i < this.itemNames.size(); i++) {
Paint itemPaint;
switch (i) {
case MyDBAdapter.KEY_ID_COLUMN /*0*/:
itemPaint = this.item1Paint;
break;
case MyDBAdapter.NAME_COLUMN /*1*/:
itemPaint = this.item2Paint;
break;
case MyDBAdapter.NAME_REF /*2*/:
itemPaint = this.item3Paint;
break;
case 3:
itemPaint = this.item4Paint;
break;
case 4:
itemPaint = this.item5Paint;
break;
case 5:
itemPaint = this.item6Paint;
break;
case 6:
itemPaint = this.item7Paint;
break;
case 7:
itemPaint = this.item8Paint;
break;
case 8:
itemPaint = this.item9Paint;
break;
case 9:
itemPaint = this.item10Paint;
break;
case 10:
itemPaint = this.item11Paint;
break;
case 11:
itemPaint = this.item12Paint;
break;
case 12:
itemPaint = this.item13Paint;
break;
case 13:
itemPaint = this.item14Paint;
break;
case 14:
itemPaint = this.item15Paint;
break;
default:
itemPaint = this.item1Paint;
break;
}
offSet = ((float) i) * (-incr);
canvas.save();
canvas.rotate(offSet, (float) this.px, (float) this.py);
canvas.drawArc(myCircleBox, (-incr) / 2.0f, incr, true, itemPaint);
this.item = ((String) this.itemNames.get(i)).toString();
this.itemLength = (float) ((int) this.textPaint.measureText(this.item));
if (((double) this.itemLength) > ((double) this.radius) * 0.8d) {
this.item = this.item.substring(0, (int) (((double) this.item.length()) * ((((double) this.radius) * 0.8d) / ((double) ((int) this.textPaint.measureText(this.item))))));
this.itemLength = (float) ((int) this.textPaint.measureText(this.item));
}
// canvas.drawText(this.item, (((float) this.px) + (this.radius / 2.0f)) - (this.itemLength / 2.0f), (float) (this.py + ((int) (((double) this.textPaint.measureText("yY")) / 2.5d))), this.textPaint);
Bitmap icon = BitmapFactory.decodeResource(getResources(),R.drawable.ic_laun);
//drawImage(canvas, tempAngle,icon );
tempAngle += sweepAngle;
canvas.restore();
}
for (i = 0; i < this.itemNames.size(); i++) {
offSet = ((float) i) * incr;
canvas.save();
canvas.rotate(offSet, (float) this.px, (float) this.py);
canvas.save();
canvas.rotate(incr / 2.0f, (float) this.px, (float) this.py);
canvas.drawLine(((float) this.px) + this.radius, (float) this.py, (float) this.px, (float) this.py, this.markerPaint);
Bitmap icon =
BitmapFactory.decodeResource(getResources(),R.drawable.ic_laun);
drawImage(canvas, tempAngle,icon );
canvas.restore();
canvas.restore();
}
canvas.restore();
canvas.drawCircle((float) this.px, (float) this.py, this.radius, this.circlePaint);
canvas.drawCircle((float) this.px, (float) this.py, this.radius + (this.circlePaint.getStrokeWidth() * 0.5f), this.rimPaint);
canvas.drawCircle((float) this.px, (float) this.py, 2.0f, this.rimPaint);
canvas.drawCircle((float) this.px, (float) this.py, 1.0f, this.rimPaint);
canvas.drawArc(rectF, 250.0f, 40.0f, true, this.textPaint);
canvas.drawArc(rectF, 250.0f, 40.0f, true, this.pointerPaint);
if (actualRotation < 0.0d) {
actualRotation += 360.0d;
} else if (actualRotation > 360.0d) {
actualRotation -= 360.0d;
}
if (!(this.selected == -1 || this.selected == ((int) (actualRotation / ((double) incr))) || !Prefs.getMusic(getContext()) || this.resourcePlayer == null)) {
if (this.resourcePlayer.isPlaying()) {
this.resourcePlayer.seekTo(0);
} else {
this.resourcePlayer.start();
}
}
this.selected = (int) (actualRotation / ((double) incr));
if (this.lifted) {
this.winner = ((String) this.itemNames.get(this.selected)).toString();
}
canvas.drawText(this.winner, (float) (this.px - (((int) this.titlePaint.measureText(this.winner)) / 2)), (((float) this.py) + this.radius) + ((float) (getMeasuredWidth() / 10)), this.titlePaint);
canvas.drawText(this.listName, (float) (this.px - (((int) this.titlePaint.measureText(this.listName)) / 2)), (((float) this.py) - this.radius) - ((float) (getMeasuredWidth() / 18)), this.titlePaint);
if (this.lifted) {
long currentTimeMillis;
if (this.lastTheta > 0.0d) {
currentTimeMillis = System.currentTimeMillis();
this.currTime = currentTimeMillis;
this.timeDiff = currentTimeMillis - this.oldTime;
this.oldTime = this.currTime;
setRotation(getRotationNumber() + this.lastTheta);
this.lastTheta -= (double) (0.002f * ((float) this.timeDiff));
if (this.lastTheta <= 0.0d) {
this.lifted = false;
Log.e("#finalDone","finalDone"+getRotationNumber());
Log.e("#offset","finalDone"+offSet);
Intent intent=new Intent(mContext, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
mContext.startActivity(intent);
}
} else {
currentTimeMillis = System.currentTimeMillis();
this.currTime = currentTimeMillis;
this.timeDiff = currentTimeMillis - this.oldTime;
this.oldTime = this.currTime;
setRotation(getRotationNumber() + this.lastTheta);
this.lastTheta += (double) (0.002f * ((float) this.timeDiff));
if (this.lastTheta >= 0.0d) {
this.lifted = false;
Log.e("#finalDone","finalDone"+getRotationNumber());
Intent intent=new Intent(mContext, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
mContext.startActivity(intent);
}
}
invalidate();
}
}
}
private void drawImage(Canvas canvas, float tempAngle, Bitmap bitmap) {
//get every arc img width and angle
int mWheelItemssize=6;
int imgWidth = (int)radius / 6;
float angle = (float) ((tempAngle + 360 / mWheelItemssize / 2) * Math.PI / 180);
//calculate x and y
int x = (int) (center + (int)radius / 2 / 2 * Math.cos(angle));
int y = (int) (center + (int) radius / 2 / 2 * Math.sin(angle));
Rect rect = new Rect(x - imgWidth /2, y - imgWidth / 2, x + imgWidth / 2, y + imgWidth / 2);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), null, true);
canvas.drawBitmap(bitmap, null, rect, null);
}
private void drawImage1(Canvas canvas, float tmpAngle, Bitmap bitmap) {
int imgWidth = (int) (radius / itemNames.size());
float angle = (float) ((tmpAngle + 360 / itemNames.size() / 2) * Math.PI / 180);
int x = (int) (center + radius / 2 / 2 * Math.cos(angle));
int y = (int) (center + radius / 2 / 2 * Math.sin(angle));
Rect rect = new Rect(x - imgWidth/2, y - imgWidth/2, x + imgWidth/2, y + imgWidth/2);
canvas.drawBitmap(bitmap, null, rect, null);
}
void OnDestroy() {
if (this.resourcePlayer != null) {
this.resourcePlayer.release();
}
}
public void autoSpin(float seed) {
if (seed >= 20.0f) {
seed = 15.0f;
}
seed = 8.0f;
this.oldTime = System.currentTimeMillis();
this.currTime = System.currentTimeMillis();
Log.e("##oldTime", String.valueOf(System.currentTimeMillis()));
Log.e("##Random", String.valueOf((new Random().nextFloat())));
Log.e("##Random", String.valueOf((new Random().nextFloat())));
int randomno=3;
this.lastTheta = (double) ((randomno * seed));
Log.e("##lastTheta", String.valueOf(lastTheta));
this.lifted = true;
invalidate();
}
}
HomeActivity
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.autoSpinButton:
// wheelView.rotateWheelTo(wheelView,3);
autoSpinButton.setEnabled(false);
Log.e("###Seed", String.valueOf(20.0f * (320.0f / width)));
wheelView.autoSpin(5.0);
break;
}
}
main Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.spin.wheel.widgets.WheelView
android:id="#+id/wheelView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/backrepeat"/>
<Button
android:id="#+id/autoSpinButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:layout_centerInParent="true"
android:text="SPIN" />
</RelativeLayout>
Please Help
I am a newbie and trying to move a ball at a slope. Here is the code where I am giving coordinates (100,300,300,600) to move the ball in a slope but it's getting away from the the slope line. Here's the code: -
import javax.swing.*;
import java.awt.*;
public class AgentMotion extends JPanel implements Runnable
{
Color color = Color.red;
int dia = 0;
long delay = 40;
private double x;
private double y;
private double x1;
private double y1;
private int dx = 1;
private int dy = 1;
private int dv = 1;
private double direction;
double a;
double b;
double a1;
double b1;
public void abc(double x, double y, double x2, double y2) {
this.x = x;
this.y = y;
this.x1 = x2;
this.y1 = y2;
this.direction=Math.toRadians(Math.atan2(x1-x,y1-y));
System.out.println("segfewg"+direction);
this.a = x;
this.b = y;
this.a1 = x1;
this.b1 = y1;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
//int x=100;
//int y=200;
int x3=(int)this.x;
int y3=(int)this.y;
g.fillOval(x3,y3,5,5); // adds color to circle
g.setColor(Color.black);
g2.drawOval(x3,y3,5,5); // draws circle
g2.drawLine(100, 300, 300, 600);
}
public void run() {
if(direction<0)
{
System.out.println("refregreg");
while(dy!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
else
{
while(dx!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
}
public void move() {
if(direction>0)
{
if(x + dv*Math.cos(direction) <a ||x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x += dx;
}
else
{
System.out.println(x + dia + dv * Math.cos(direction));
if(x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x -= dx;
}
}
public void move2() {
if(direction>0)
{
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y > b1) {
dy *= 0;
color = getColor();
}
y += dy;
}
else
{
System.out.println(dv * Math.sin(direction) + dia + y);
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y < b1) {
dy *= 0;
color = getColor();
}
y -= dy;
}
}
public Color getColor() {
int rval = (int)Math.floor(Math.random() * 256);
int gval = (int)Math.floor(Math.random() * 256);
int bval = (int)Math.floor(Math.random() * 256);
return new Color(rval, gval, bval);
}
public void start() {
while(dx==0) {
try {
System.out.println("jiuj");
Thread.sleep(25);
} catch(InterruptedException e) {
System.out.println("dwdwdwd");
}
}
Thread thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
}
A few suggestions
dx and dy should be double
atan is overkill as #Spektre says. What you want is much more simple to calculate direction.
this.direction = (y2 - y) / (x2 - x)
If we give (100,300,300,600) as the arguments to abc (which would presumably be a constructor for this class), the slope is 1.5. Therefore we could say:
dx = 1.0
dy = 1.5
and this would keep on the line perfectly. For the general case where you want to change the begin and the end point, you have to calculate the ratio. So you could set either dx or dy to 1.0 and then set the other one so that the ratio is maintained. Something like the following mathematical pseudocode:
dx = (x2 - x) / minimum(x2-x, y2-y)
dy = (y2 - y) / minimum(x2-x, y2-y)
I am trying to get the x and y value of a point after increasing the distance r. Perhaps there is a better way of calculate the angle phi too, so that I don't need to check in which quadrant the point is. The 0-point is at the half of the width and height of the window. Here is my attempt:
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
public final class Laser extends java.applet.Applet implements Runnable{
private static final long serialVersionUID = -7566644836595581327L;
Thread runner;
int width = 800;
int height = 600;
Point point = new Point(405,100);
Point point1 = new Point(405,100);
public void calc(){
int x = getWidth()/2;
int y = getHeight()/2;
int px = point.x;
int py = point.y;
int px1 = point1.x;
int py1 = point1.y;
double r = 0;
double phi = 0;
// Point is in:
// Quadrant 1
if(px > x && py < y){
r = Math.hypot(px1-x, y-py1);
phi = Math.acos((px1-x)/r)*(180/Math.PI);
}/*
// Quadrant 2
else if(px < x && py < y){
r = Math.hypot(x-px, y-py);
phi = Math.acos((px-x)/r)*(180/Math.PI);
}
// Quadrant 3
else if(px < x && py > y){
r = Math.hypot(x-px, py-y);
phi = Math.acos((px-x)/r)*(180/Math.PI)+180;
}
// Quadrant 4
else if(px > x && py > y){
r = Math.hypot(px-x, py-y);
phi = Math.acos((px-x)/r)*(180/Math.PI)+180;
}*/
r += 1;
point1.x = (int) (r*Math.cos(phi));
point1.y = (int) (r*Math.sin(phi));
System.out.println(r+";"+point1.x+";"+point1.y);
}
public void paint(Graphics g) {
g.setColor(Color.ORANGE);
calc();
g.drawLine(point.x, point.y, point1.x, point1.y);
int h = getHeight();
int w = getWidth();
g.setColor(Color.GREEN);
g.drawLine(0, h/2, w, h/2);
g.drawLine(w/2, 0, w/2, h);
}
/*
public void initPoints(){
for(int i = 0; i < pointsStart.length; i++){
int x = (int)(Math.random()*getWidth());
int y = (int)(Math.random()*getHeight());
pointsStart[i] = pointsEnd[i] = new Point(x,y);
}
}
*/
public void start() {
if (runner == null) {
runner = new Thread(this);
setBackground(Color.black);
setSize(width, height);
//initPoints();
runner.start();
}
}
#SuppressWarnings("deprecation")
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
public void run() {
while (true) {
repaint();
try { Thread.sleep(700); }
catch (InterruptedException e) { }
}
}
public void update(Graphics g) {
paint(g);
}
}
You are changing (x,y) to be r from some other point, when it had previously been some distance r' from that point, correct? So why not avoid the trigonometry, and just scale each of the components from that point by r/r'?
Edit: ok, iterate over the pixels along whichever component (x or y) is longer (let's assume it's y); for each xi in (0..x), yi = xi*(y/x), and you plot (xi,yi).
Keep it simple! And use double variables for such computations, I changed it for you.
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.Point2D;
public final class Laser extends java.applet.Applet implements Runnable {
private static final long serialVersionUID = -7566644836595581327L;
Thread runner;
int width = 800;
int height = 600;
Point2D.Double point = new Point2D.Double(400, 100);
Point2D.Double point1 = new Point2D.Double(405, 102);
public void calc() {
double px = point.x;
double py = point.y;
double px1 = point1.x;
double py1 = point1.y;
double dx = px1 - px;
double dy = py1 - py;
double len = Math.hypot(dx, dy);
double newlen = len+2;
double coeff = Math.abs((newlen-len)/len);
point1.x += dx * coeff;
point1.y += dy * coeff;
System.out.println(len+";"+point1.x+";"+point1.y);
}
public void paint(Graphics g) {
g.setColor(Color.ORANGE);
calc();
g.drawLine((int)point.x, (int)point.y, (int)point1.x, (int)point1.y);
int h = getHeight();
int w = getWidth();
g.setColor(Color.GREEN);
g.drawLine(0, h / 2, w, h / 2);
g.drawLine(w / 2, 0, w / 2, h);
}
/*
* public void initPoints(){
*
* for(double i = 0; i < pointsStart.length; i++){ double x =
* (double)(Math.random()*getWidth()); double y =
* (double)(Math.random()*getHeight()); pointsStart[i] = pointsEnd[i] = new
* Point(x,y); }
*
* }
*/
public void start() {
if (runner == null) {
runner = new Thread(this);
setBackground(Color.black);
setSize(width, height);
// initPoints();
runner.start();
}
}
#SuppressWarnings("deprecation")
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
public void run() {
while (true) {
repaint();
try {
Thread.sleep(700);
}
catch (InterruptedException e) {
}
}
}
public void update(Graphics g) {
paint(g);
}
}