Path not drawing to canvas in android app - android

I load float values on two List arrays on a thread.
Once the values have been loaded, the arrays are set to two MainActivity static List arrays.
The values load perfectly into the List arrays. In my DummyDraw class which extends Drawable and overrides onDraw(), I am able to draw circles based on the values located inside the MainActivity List arrays, but when I try
to create a path object and load the values to the path object, and afterwards try to draw the path, it won't draw. Here's the code inside onDraw():
//inside onDraw() on DummyDraw class which extends Draw-able:
//in the constructor:
path = new path();
//inside onDraw():
for(int u = 0; u < MainActivity.valueList.size(); u++){
float x = MainActivity.valueList.get(u);
float y = MainActivity.valueList2.get(u);
if(u==0)path.moveTo(x,y);else path.lineTo(x,y);
//canvas.drawCircle(x,y,0.5f*densityMultiplier,points);
}
canvas.drawPath(path,points);// this doesn't draw anything to the screen
Any ideas or suggestions, thanks.

After much trial and error and reading about the quadto and rQuadTo methods, I found a way to create a very excellent approximation of a smooth curve for my graphing function needs:
using the notion of previous and current point on the List arrays:
for(int u = 0; u < MainActivity.valueList.size(); u++){
float x = MainActivity.valueList.get(u);//current point: x value
float y = MainActivity.valueList2.get(u);//current point: y value
if(u!=0){
float previousX = MainActivity.valueList.get(u-1);
float previousY = MainActivity.valueList2.get(u-1);
float middle1 = (previousX + x)/2f;
float middle2 = (previousY + y)/2f;
path.moveTo(previousX,previousY);
path.quadTo(x,y,middle1,middle2);
path.lineTo(x,y);
canvas.drawPath(path,points);//points is the name of my paint object
path.reset();//this is probably the most important line for it to work
}
}
the code above will iterate through two arrays that holds x and y coordinates and create a very excellent looking smooth curve. However, upon zooming into my view I can see some slight blurriness in my curve. Does anyone know what should I do with my paint object to eliminate this blurriness?

Related

Visualisation of a boardgame

I'm new to android studio and I'm learning a lot right now. But I'm stuck now, I want to create something like a container for a 16x7 boardgame with individual fields. I think theres better ways to do this and I'm trying around since 2 hours, with no success. Right now I'm using a Grid View to display my String[] with an array adapter to a simple selectable list item, but it doesn't scale right and I need to scroll down to see all of the fields, which is bad for a videogame.
Tl,dr: I'd like to display an array of 112 elements like a boardgame, what container can I use to create those individual fields, maybe even set the amounts of rows(7) and columns(16), and display it simple like an actual boardgame?
I would render bitmap tiles to the Canvas. Below code is just an outline:
// You will set this frameBuffer to an ImageView in the app's main screen.
// You should set the ImageView's ScaleType properly.
Bitmap frameBuffer = Bitmap.createBitmap(
TILE_SIZE * 16, TILE_SIZE * 7, Bitmap.Config.ARGB_8888
);
Canvas canvas = new Canvas(frameBuffer);
Paint paint = new Paint();
for (int y = 0; y < 7; y++) {
for (int x = 0; x < 16; x++) {
// You are supposed to define bitmapTiles.get() method elsewhere.
canvas.drawBitmap(
bitmapTiles.get(x, y), TILE_SIZE * x, TILE_SIZE * y, paint
);
}
}

Line Drawing on stage

There are few actors on stage, lines are drawn connecting centers of them, like a graph, Nodes and edges. Nodes are gradable. On Drag I am using the following code
public void touchDragged(InputEvent event, float eventOffsetX, float
eventOffsetY, int pointer)
{
float deltaX = eventOffsetX - self.grabOffsetX;
float deltaY = eventOffsetY - self.grabOffsetY;
self.moveBy(deltaX, deltaY);
moveCoordinatesBy((int)deltaX,(int)deltaY);
}
the Method moveCoordinatesBy is updating the coordinate of the center of the node. which is used to draw lines (Edges) connecting the. This is working Fine.
My problem is - When I am using moveTo action for Nodes, I need to update edges at the same time. For this I need to update coordinates of there center. To do this I am using the following code in the act method of the Node -
public void act(float dt)
{
super.act(dt);
Vector2 loc = new Vector2();
loc.x = self.getX()+ self.getWidth()/2;
loc.y = self.getY() + self.getHeight()/2;
Vector2 v = new Vector2();
v = self.localToStageCoordinates(loc);
setCoordinates((int)v.x, (int)v.y);
}
The coordinates I am getting are not center of the node, they are almost multiplied by 2. Am I doing something wrong?
And also getWidth() and self.getHeight() returning double the size. When actor (node) is scaled getWidth() and self.getHeight() are returning arbitery values depending on how for it is located on stage. Further from (0,0) larger the returned value.
v = self.localToStageCoordinates(loc);
above line of code not needed, beacuse all the actors were directly added to the stage. By removing localToStageCoordinates(loc) its working fine now.

How to display X and Y axis for XYPlot in AndroidPlot

Background
I'm developing an app for Android that plots data as a line graph using AndroidPlot. Because of the nature of the data, it's important that it be pannable and zoomable. I'm using AndroidPlot's sample code on bitbucket for panning and zooming, modified to allow panning and zooming in both X and Y directions.
Everything works as desired except that there are no X and Y axis lines. It is very disorienting to look at the data without them. The grid helps, but there's no guarantee that grid lines will actually fall on the axis.
To remedy this I have tried adding two series, one that falls on just the X axis and the other on the Y. The problem with this is that if one zooms out too far the axis simply end, and it becomes apparent that I have applied a 'hack'.
Question
Is it possible to add X and Y axis lines to AndroidPlot? Or will my sad hack have to do?
EDIT
Added tags
I figured it out. It wasn't trivial, took a joint effort with a collaborator, and sucked up many hours of our time.
Starting with the sample mentioned in my question, I had to extend XYPlot (which I called GraphView) and override the onPreInit method. Note that I have two PointF's, minXY and maxXY, that are defined in my overridden XYPlot and manipulated when I zoom or scroll.
#Override
protected void onPreInit() {
super.onPreInit();
final Paint axisPaint = new Paint();
axisPaint.setColor(getResources().getColor(R.color.MY_AXIS_COLOR));
axisPaint.setStrokeWidth(3); //or whatever stroke width you want
XYGraphWidget oldWidget = getGraphWidget();
XYGraphWidget widget = new XYGraphWidget(getLayoutManager(),
this,
new SizeMetrics(
oldWidget.getHeightMetric(),
oldWidget.getWidthMetric())) {
//We now override XYGraphWidget methods
RectF mGridRect;
#Override
protected void doOnDraw(Canvas canvas, RectF widgetRect)
throws PlotRenderException {
//In order to draw the x axis, we must obtain gridRect. I believe this is the only
//way to do so as the more convenient routes have private rather than protected access.
mGridRect = new RectF(widgetRect.left + ((isRangeAxisLeft())?getRangeLabelWidth():1),
widgetRect.top + ((isDomainAxisBottom())?1:getDomainLabelWidth()),
widgetRect.right - ((isRangeAxisLeft())?1:getRangeLabelWidth()),
widgetRect.bottom - ((isDomainAxisBottom())?getDomainLabelWidth():1));
super.doOnDraw(canvas, widgetRect);
}
#Override
protected void drawGrid(Canvas canvas) {
super.drawGrid(canvas);
if(mGridRect == null) return;
//minXY and maxXY are PointF's defined elsewhere. See my comment in the answer.
if(minXY.y <= 0 && maxXY.y >= 0) { //Draw the x axis
RectF paddedGridRect = getGridRect();
//Note: GraphView.this is the extended XYPlot instance.
XYStep rangeStep = XYStepCalculator.getStep(GraphView.this, XYAxisType.RANGE,
paddedGridRect, getCalculatedMinY().doubleValue(),
getCalculatedMaxY().doubleValue());
double rangeOriginF = paddedGridRect.bottom;
float yPix = (float) (rangeOriginF + getRangeOrigin().doubleValue() * rangeStep.getStepPix() /
rangeStep.getStepVal());
//Keep things consistent with drawing y axis even though drawRangeTick is public
//drawRangeTick(canvas, yPix, 0, getRangeLabelPaint(), axisPaint, true);
canvas.drawLine(mGridRect.left, yPix, mGridRect.right, yPix, axisPaint);
}
if(minXY.x <= 0 && maxXY.x >= 0) { //Draw the y axis
RectF paddedGridRect = getGridRect();
XYStep domianStep = XYStepCalculator.getStep(GraphView.this, XYAxisType.DOMAIN,
paddedGridRect, getCalculatedMinX().doubleValue(),
getCalculatedMaxX().doubleValue());
double domainOriginF = paddedGridRect.left;
float xPix = (float) (domainOriginF - getDomainOrigin().doubleValue() * domianStep.getStepPix() /
domianStep.getStepVal());
//Unfortunately, drawDomainTick has private access in XYGraphWidget
canvas.drawLine(xPix, mGridRect.top, xPix, mGridRect.bottom, axisPaint);
}
}
};
widget.setBackgroundPaint(oldWidget.getBackgroundPaint());
widget.setMarginTop(oldWidget.getMarginTop());
widget.setMarginRight(oldWidget.getMarginRight());
widget.setPositionMetrics(oldWidget.getPositionMetrics());
getLayoutManager().remove(oldWidget);
getLayoutManager().addToTop(widget);
setGraphWidget(widget);
//More customizations can go here
}
And that was that. I sure wish this was built into AndroidPlot; it'll be nasty trying to fix this when it breaks in an AndroidPlot update...

Android: onDraw method using DrawPoint() causing jitter and distortion on canvas

I am developing an app which draws more or less a two-dimensional matrix of values to a canvas. The values of this matrix are scaled to Alpha levels to illustrate intensity, and the coordinates for the matrix are simply extrapolated from row and column indexes. Below is my onDraw routine.
public void onDraw(Canvas canvas, float [][] spectrum, float nsegs,int seglen) {
//canvas.translate(0,0);
//alpha = 0;
int canHeight = canvas.getHeight();
int canWidth = canvas.getWidth();
//float[] array = generateData(512);
float [] spec = new float[seglen];
final float bw = (float)(canWidth-2)/nsegs;
final float bh = (float)(canHeight-2)/(float) seglen;
for (int i = 0;i<seglen;i++){
spec[i] = spectrum[i][index]; // One column at a time
}
float max = maxVal(spec);
float min = minVal(spec);
xcoor = index;
for (int n = 0; n < seglen; n++){
//Scale value to alpha (0-255)
alpha =(int)Math.round((((spec[n] - min)/max)*255.0));
ycoor = n;
paint.setAlpha(alpha);
canvas.drawPoint(xcoor,ycoor, paint);
}
index = (int) (index +1);
if (index == nsegs-1){
index = 0;
}
}
Here paint configuration is pre-defined as:
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(2);
This program draws one pixel at a time, fills one column of pixels equal to the number of elements in a column of the matrix. Then it starts on the next column, where the previous column is still displayed and so forth. At this stage when all columns are full it stars from the first column again, drawing on top of previous elements.
The Problem: The tailing columns although already drawn appear to flicker and jump around, as does the Alpha. I have attempted to canvas.save() and canvas.restore() to capture the entire canvas and restore it after a column is printed. I have double checked all my row and column indexing and alpha vales to ensure the coordinates increment as per desired (and they do). This is very similar to the sample APIdemo DrawPoints.java, however there are three primary differences.
I am using DrawPoint not DrawPoints, and
I don't use "canvas.setColour" as it removes the tailing columns from the canvas.
This onDraw function is operating in a Thread which extends SurfaceView
Any idea's would be much appreciated, thank you for your time.
In the case above, I was using a SurfaceView instead of a View. Out of the Android dev docs
Note: On each pass you retrieve the Canvas from the SurfaceHolder, the previous state of the Canvas will be retained. In order to properly animate your graphics, you must re-paint the entire surface. For example, you can clear the previous state of the Canvas by filling in a color with drawColor() or setting a background image with drawBitmap(). Otherwise, you will see traces of the drawings you previously performed.
The Solution, re-draw the entire canvas each time to prevent the jitter.

Android path to array - read the points on a path?

Is there a way to read the points created when drawing a path? It seems silly to me that a path cannot be readable.
Or is it just better to manually write the current finger position to an array?
thanks
You can read as many points as you want from any path.
Example how to read coordinates from the middle of path:
PathMeasure pm = new PathMeasure(myPath, false);
//coordinates will be here
float aCoordinates[] = {0f, 0f};
//get coordinates of the middle point
pm.getPosTan(pm.getLength() * 0.5f, aCoordinates, null);
You can pass any distance from the path start to get point coordinates.
As far as I know, I think that you can't get previously added points, but you can extend Path class and create your own, override add methods, and then store that points in an array or a list or whatever you prefer.
You mentioned finger position in your question. If you are drawing and using motion events, you could add the X and Y positions to an ArrayList during the event where all even indices are X's and odds are Y's. I used this in a couple of drawing apps I created. To recreate the path all you need is a for loop and Path.lineTo().
Also if you have drawn the path to a view with a specific color, say Color.Black, you can use Bitmap.getPixels(...) and create an array {x0,y0,x1,y1,....xn,yn} based off a for loop like
int i = 0;
for(int y = 0; y < bitmap.getHeight(); y++){
for(int x = 0; x < bitmap.getWidth(); x++){
if(pixels[y*bitmap.getWidth()+x] == Color.BLACK){
xy[i] = x;
i++;
xy[i] = y;
i++;
}
}
}
The array xy has all your coordinates.

Categories

Resources