Fill arrow head goes off in line in canvas Android - android

The arrow head with stroke working fine in canvas, but the filled arrow head is not drawing at the right position ,Here is my code for draw arrow.
private void drawArrow(Point startPoint, Point endPoint, Paint paint, Canvas mCanvas) {
Path mPath = new Path();
float deltaX = endPoint.x - startPoint.x;
float deltaY = endPoint.y - startPoint.y;
//float frac = (float) 0.1;
int ARROWHEAD_LENGTH = 15;
float sideZ = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY);
float frac = ARROWHEAD_LENGTH < sideZ ? ARROWHEAD_LENGTH / sideZ : 1.0f;
float point_x_1 = startPoint.x + (float) ((1 - frac) * deltaX + frac * deltaY);
float point_y_1 = startPoint.y + (float) ((1 - frac) * deltaY - frac * deltaX);
float point_x_2 = endPoint.x;
float point_y_2 = endPoint.y;
float point_x_3 = startPoint.x + (float) ((1 - frac) * deltaX - frac * deltaY);
float point_y_3 = startPoint.y + (float) ((1 - frac) * deltaY + frac * deltaX);
mPath.moveTo(point_x_1, point_y_1);
mPath.lineTo(point_x_2, point_y_2);
mPath.lineTo(point_x_3, point_y_3);
//mPath.lineTo(point_x_1, point_y_1);
//mPath.lineTo(point_x_1, point_y_1);
mCanvas.drawPath(mPath, paint);
invalidate();
}

to resolve this issue, I have placed the end line to the center of triangle.
You can do it with this formula :
float endLineX = (point_x_1 + point_x_2 + point_x_3) / 3;
float endLineY = (point_y_1 + point_y_2 + point_y_3) / 3;
Voilà

Related

Draw arrow according to path

Currently I'm drawing a arrow head to my canvas by doing the following:
mPaint.setStyle(Style.FILL);
float deltaX = this.mPoints[1].x - this.mPoints[3].x;
float deltaY = this.mPoints[1].y - this.mPoints[3].y;
float frac = (float) 0.1;
float point_x_1 = this.mPoints[3].x + (1 - frac) * deltaX + frac * deltaY;
float point_y_1 = this.mPoints[3].y + (1 - frac) * deltaY - frac * deltaX;
float point_x_2 = this.mPoints[1].x;
float point_y_2 = this.mPoints[1].y;
float point_x_3 = this.mPoints[3].x + (1 - frac) * deltaX - frac * deltaY;
float point_y_3 = this.mPoints[3].y + (1 - frac) * deltaY + frac * deltaX;
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(point_x_1, point_y_1);
path.lineTo(point_x_2, point_y_2);
path.lineTo(point_x_3, point_y_3);
path.lineTo(point_x_1, point_y_1);
path.lineTo(point_x_1, point_y_1);
path.close();
canvas.drawPath(path, mPaint);
The above works fine. The problem I have is that the direction of the arrow is always pointing to the top right corner of my screen.
MY QUESTION:
How can I modify, what I already have, to draw the arrow in the direction of of my onTouchEvent?
It's also worth mentioning that I already get the direction in my onTouchEvent that I pass to my onDraw as shown below:
//Starting point X
float startX = mX; // MotionEvent.ACTION_DOWN ---> mX = event.getX();
//Starting point Y
float startY = mY; // MotionEvent.ACTION_DOWN ---> mY = event.getY();
//Move to X
float stopX = pX; // MotionEvent.ACTION_MOVE ---> pX = event.getX();
//Move to Y
float stopY = pY; // MotionEvent.ACTION_MOVE ---> pY = event.getY();
Using the above, when I draw a line, I would call:
canvas.drawLine(startX, startY, stopX, stopY, mPaint);
This will draw the line in the direction I want.
The problem is that canvas.drawPath takes 2 fields path and paint where canvas.drawLine takes 5 fields startX, startY, stopX, stopY, paint.
Any advise would greatly be appreciated.

image deformation in an android project

In my android app, I need to deform the image from one point to the other point.
It should seems like that
the origin point A and the B is the new position of A
the result may like that
I have try to use the "drawBitmapMesh" function to make it possible, but did not reach, here is the wrap code:
public void warp(float startX, float startY, float endX, float endY) {
float ddPull = (endX - startX) * (endX - startX) + (endY - startY) * (endY - startY);
float dPull = (float) Math.sqrt(ddPull);
for (int i = 0; i < (COUNTS * 2); i += 2) {
float dx = orig[i] - startX;
float dy = orig[i + 1] - startY;
float dd = dx * dx + dy * dy;
float d = (float) Math.sqrt(dd);
// do deformation when the point is in the circle
if (d < cirR) {
double e =(cirR * cirR - dd) * (cirR * cirR - dd) / ((cirR * cirR - dd + dPull * dPull) * (cirR * cirR - dd + dPull * dPull));
double pullX = e * (endX - startX);
double pullY = e * (endY - startY);
verts[i] = (float) (orig[i] + pullX);
verts[i + 1] = (float) (orig[i + 1] + pullY);
}
}
invalidate();
}
At last I solve it by myself, i use the GPUimage for Android and write a customized filter by GLSL, it works good~!

Android View Invalidate optimization idea

I'm trying to make an animation on my android application.
I have a list of View I want to draw every 10 ms to have a smooth animations.
class CircularAnimationSector extends View{
private double scale;
private double circularPosition;
private double circularLength;
private double sectionRadiusRatio;
private double circularSpeed;
private int color;
private Paint paint = new Paint();
private ICircular iCircular;
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
Path path = new Path();
int width = this.getWidth();
// int height = this.getHeight();
Point center = new Point((int)(width / 2.0f), (int)(width / 2.0f));
int innerWidthRadius = (int) (this.iCircular.GetViewSize() / 2.0f);
float startRadius = (float)(innerWidthRadius * this.iCircular.GetStartRatio());
float endRadius = (float)(startRadius + this.scale * (this.sectionRadiusRatio - this.iCircular.GetStartRatio()) * innerWidthRadius);
float startAngle = (float)(this.circularPosition - this.circularLength / 2.0f);
float endAngle = (float)(this.circularPosition + this.circularLength / 2.0f);
Point p1 = new Point((int) (center.x + startRadius * Math.cos(startAngle)), (int) (center.y + startRadius * Math.sin(startAngle)));
Point p3 = new Point((int) (center.x + endRadius * Math.cos(endAngle)), (int) (center.y + endRadius * Math.sin(endAngle)));
// PATH DRAWING
path.moveTo((float) (p1.x), (float) (p1.y));
path.arcTo(new RectF(center.x - startRadius, center.y - startRadius, center.x + startRadius, center.y + startRadius), (float) (startAngle * 180 / Math.PI), (float) ((endAngle - startAngle) * 180 / Math.PI));
path.lineTo((float) (p3.x), (float) (p3.y));
path.arcTo(new RectF(center.x - endRadius, center.y - endRadius, center.x + endRadius, center.y + endRadius), (float) (endAngle * 180 / Math.PI), (float) ((startAngle - endAngle) * 180 / Math.PI));
path.lineTo((float) (p1.x), (float) (p1.y));
canvas.drawPath(path, this.paint);
this.circularPosition += this.circularSpeed;
}
}
But it seems that the animation is not as smooth as expected and the application lag a little.
Do you have any advice to optimize my animation ?
I just want to draw a view every 10 ms (for instance) and then upadte its position and draw it again around a circle.

rotation of line in an android canvas

i've a math problem, i create a line with each extremety, a perpendicular line but i would like to choose the length of these perpendicular lines but i don't know how to do this :(
this is my code :
int vX = fleche.endPoint.x - fleche.startPoint.x;
int vY = fleche.endPoint.y - fleche.startPoint.y;
int vXP = - ( fleche.endPoint.y - fleche.startPoint.y );
Paint p = new Paint();
p.setColor(fleche.color);
p.setTextSize(30);
p.setTextAlign(Paint.Align.CENTER);
p.setStrokeWidth(8);
p.setAlpha(fleche.alpha);
Path path = new Path();
path.moveTo(fleche.startPoint.x - 10,fleche.startPoint.y - 10);
path.lineTo(fleche.endPoint.x - 10, fleche.endPoint.y - 10);
c.drawTextOnPath(fleche.value + fleche.unit, path, 30, 0, p);
c.drawPath(path, p);
path.moveTo(fleche.startPoint.x - 10,fleche.startPoint.y - 10);
path.lineTo(fleche.endPoint.x - 10, fleche.endPoint.y - 10);
c.drawTextOnPath(fleche.value + fleche.unit, path, 30, 0, p);
//ligne principale
c.drawLine(fleche.startPoint.x, fleche.startPoint.y, fleche.endPoint.x, fleche.endPoint.y, p);
//left
c.drawLine(fleche.startPoint.x, fleche.startPoint.y, fleche.startPoint.x + vXP, fleche.startPoint.y + vX, p);
c.drawLine(fleche.startPoint.x, fleche.startPoint.y, fleche.startPoint.x - vXP, fleche.startPoint.y - vX, p);
//right
c.drawLine(fleche.endPoint.x, fleche.endPoint.y, fleche.endPoint.x + vXP, fleche.endPoint.y + vX, p);
c.drawLine(fleche.endPoint.x, fleche.endPoint.y, fleche.endPoint.x - vXP, fleche.endPoint.y - vX, p);
//Tools.logDebug("Fleche créée(" + i + "/" + (arrows.size()-1) + ") :" + fleche.toString());
Thanks in advance to all :D
This is how you can scale dx and dy to length L:
float ratio = L / Math.sqrt(dx * dx + dy * dy);
dx *= ratio;
dy *= ratio;
edit after comment:
//left
final float L = 20.0f; // for instance
final float ratio = L / Math.sqrt(vXP * vXP + vX * vX);
final float dx = vXP * ratio;
final float dy = vX * ratio;
c.drawLine(fleche.startPoint.x, fleche.startPoint.y, fleche.startPoint.x + dx, fleche.startPoint.y + dy, p);
c.drawLine(fleche.startPoint.x, fleche.startPoint.y, fleche.startPoint.x - dx, fleche.startPoint.y - dy, p);

android 3d vertical carousel view

I am using http://www.codeproject.com/Articles/146145/Android-3D-Carousel code to create a vertical carousel view.i can see the vertical carousel using below changes in the code but center item is not properly placed in the screen and if the list items size increased, diameter moves upwards.
private void setUpChild(CarouselImageView child, int index, float angleOffset) {
// Ignore any layout parameters for child, use wrap content
addViewInLayout(child, -1 /*index*/, generateDefaultLayoutParams());
child.setSelected(index == mSelectedPosition);
int h;
int w;
if (mInLayout)
{
h = (getMeasuredHeight() - getPaddingBottom()-getPaddingTop())/3;
w = getMeasuredWidth() - getPaddingLeft() - getPaddingRight()/3;
}
else
{
h = (getMeasuredHeight() - getPaddingBottom()-getPaddingTop())/3;
w = getMeasuredWidth() - getPaddingLeft() - getPaddingRight()/3;
}
child.setCurrentAngle(angleOffset);
// modify the diameter.
Calculate3DPosition(child, w*(getAdapter().getCount()/4), angleOffset);
// Measure child
child.measure(w, h);
int childLeft;
// Position vertically based on gravity setting
int childTop = calculateTop(child, true);
childLeft = 0;
child.layout(childLeft, childTop, w, h);
}
change in calculate3position function as below
float x = (float) (-diameter/2 * Math.cos(angleOffset) * 0.00001);
float z = diameter/2 * (1.0f - (float)Math.cos(angleOffset));
float y = (float) (diameter/2 * Math.sin(angleOffset)) + diameter/2 - child.getWidth();
child.setX(x);
child.setZ(z);
child.setY(y);
I think that this calculation:
float x = (float) (-diameter/2 * Math.cos(angleOffset) * 0.00001);
float z = diameter/2 * (1.0f - (float)Math.cos(angleOffset));
float y = (float) (diameter/2 * Math.sin(angleOffset)) + diameter/2 - child.getWidth();
should be this:
float x = 0.0f
float z = diameter/2.0f * (1.0f - (float)Math.cos(angleOffset));
float y = (diameter/2.0f * Math.sin(angleOffset)) + diameter/2.0f - child.getHeight()/2.0f;
Your x position should always be zero, and your y position should be based on the sin, and should be offset by 1/2 of the height of the child instead of 1/2 of the width.
Hello try this code and replace with this code in your Calculate3DPosition method
angleOffset = angleOffset * (float) (Math.PI / 180.0f);
float y = (float) (((diameter * 60) / 100) * Math.sin(angleOffset)) + ((diameter * 50) / 100);
float z = diameter / 2 * (1.0f - (float) Math.cos(angleOffset));
float x = (float) (((diameter * 5) / 100) * Math.cos(angleOffset) * 0.3);
child.setItemX(x);
child.setItemZ((z * 30) / 100);
child.setItemY(-(y));
its solve my problem please try this one

Categories

Resources