I have the following routine in a subclass of view:
It calculates an array of points that make up a line, then erases the previous lines, then draws the new lines (impact refers to the width in pixels drawn with multiple lines). The line is your basic bell curve, squeezed or stretched by variance and x-factor.
Unfortunately, nothing shows on the screen. A previous version with drawPoint() and no array worked, and I've verified the array contents are being loaded correctly, and I can see that my onDraw() is being triggered.
Any ideas why it might not be drawn? Thanks in advance!
protected void drawNewLine( int maxx, int maxy, Canvas canvas, int impact, double variance, double xFactor, int color) {
// impact = 2 to 8; xFactor between 4 and 20; variance between 0.2 and 5
double x = 0;
double y = 0;
int cx = maxx / 2;
int cy = maxy / 2;
int mu = cx;
int index = 0;
points[maxx<<1][1] = points[maxx<<1][0];
for (x = 0; x < maxx; x++) {
points[index][1] = points[index][0];
points[index][0] = (float) x;
Log.i(DEBUG_TAG, "x: " + x);
index++;
double root = 1.0 / (Math.sqrt(2 * Math.PI * variance));
double exponent = -1.0 * (Math.pow(((x - mu)/maxx*xFactor), 2) / (2 * variance));
double ePow = Math.exp(exponent);
y = Math.round(cy * root * ePow);
points[index][1] = points[index][0];
points[index][0] = (float) (maxy - y - OFFSET);
index++;
}
points[maxx<<1][0] = (float) impact;
for (int line = 0; line < points[maxx<<1][1]; line++) {
for (int pt = 0; pt < (maxx<<1); pt++) {
pointsToPaint[pt] = points[pt][1];
}
for (int skip = 1; skip < (maxx<<1); skip = skip + 2)
pointsToPaint[skip] = pointsToPaint[skip] + line;
myLinePaint.setColor(Color.BLACK);
canvas.drawLines(pointsToPaint, bLinePaint); // draw over old lines w/blk
}
for (int line = 0; line < points[maxx<<1][0]; line++) {
for (int pt = 0; pt < maxx<<1; pt++) {
pointsToPaint[pt] = points[pt][0];
}
for (int skip = 1; skip < maxx<<1; skip = skip + 2)
pointsToPaint[skip] = pointsToPaint[skip] + line;
myLinePaint.setColor(color);
canvas.drawLines(pointsToPaint, myLinePaint); / new color
}
}
update: Replaced the drawLines() with drawPoint() in loop, still no joy
for (int p = 0; p<pointsToPaint.length; p = p + 2) {
Log.i(DEBUG_TAG, "x " + pointsToPaint[p] + " y " + pointsToPaint[p+1]);
canvas.drawPoint(pointsToPaint[p], pointsToPaint[p+1], myLinePaint);
}
/// canvas.drawLines(pointsToPaint, myLinePaint);
I was attempting to write from within onCreate() and onStart(). The View and its Canvas are never actually rendered for the first time until the end of onStart().
aren't you suppose to call invalidate (like a mapview) to force the view to reload?
YourView.invalidate() (or maybe postInvalidate(), depending where you are : main sthread or not)
here is the detail
Related
Below is code from Google Hello AR sample which I have to modifed to find the area of selected non intersecting region, But getting wrong Area
int size = anchors.size();
arrayOfVertex = new float[size + 1][2];
Pose firstPose = getPose(anchors.get(0));
arrayOfVertex[0][0] = firstPose.tx();
arrayOfVertex[0][1] = firstPose.ty();
Pose pose0 = getPose(anchors.get(0));
for (int i = 1; i < anchors.size(); i++) {
pose1 = getPose(anchors.get(i));
float meter = (getDistance(pose0, pose1));
total += meter;
sb.append(" + ").append(String.format("%.2f", meter));
pose0 = pose1;
arrayOfVertex[i][0] = pose0.tx();
arrayOfVertex[i][1] = pose0.ty();
}
Calculating AREA from vertices obtained from Pose
area = sqrt(shoelaceFormulaToFindArea(arrayOfVertex));
final String result = "Area(m sq): " + area;
Formula which I am using to find AREA
public double shoelaceFormulaToFindArea(float[][] arr)
{
int n = arr.length;
/** copy initial point to last row **/
arr[n - 1][0] = arr[0][0];
arr[n - 1][1] = arr[0][1];
double det = 0.0;
/** add product of x coordinate of ith point with y coordinate of (i + 1)th point **/
for (int i = 0; i < n - 1; i++)
det += (double) (arr[i][0] * arr[i + 1][1]);
/** subtract product of y coordinate of ith point with x coordinate of (i + 1)th point **/
for (int i = 0; i < n - 1; i++)
det -= (double) (arr[i][1] * arr[i + 1][0]);
/** find absolute value and divide by 2 **/
det = Math.abs(det);
det /= 2;
return det;
}
Getting Wrong Area, and sometimes 0.0.
Was doing a simple mistake. I was passing ty() from the 3d plane instead of tz(). Got the area once i passed tx & tz() to shoelace formula.
I have problem where i need to add a button on center of transparent area in image.
Example:
according to above image i have hundreds of photo frame and each frame there is a transparent area and i need to add a button on center of this transparent area.
Now i want a solution in which i can get coordinates of "x" programatically.
Please help.
public static PointF getTransparentCenter(Bitmap bitmap, Point viewSize) {
List<Point> transparentPoints = new ArrayList<>();
for (int i = 0; i < bitmap.getWidth(); i++) {
for (int j = 0; j < bitmap.getHeight(); j++) {
int pixel = bitmap.getPixel(i, j);
if ((pixel & 0xff000000) == 0) {
//the point color is transparent
transparentPoints.add(new Point(i, j));
}
}
}
int totalX = 0;
int totalY = 0;
for (Point transparentPoint : transparentPoints) {
totalX += transparentPoint.x;
totalY += transparentPoint.y;
}
float centerX = (float) totalX / transparentPoints.size();
float centerY = (float) totalY / transparentPoints.size();
float x = viewSize.x * centerX / bitmap.getWidth();
float y = viewSize.y * centerY / bitmap.getHeight();
return new PointF(x, y);
}
I think this is stupid, but I think there's no other way.
I've created an application that takes an image captured by the Android device, displays this image in the ImageView. The user can then press a button to either blur or deblur the image. When I run the application on my Android device I can take an image with the camera and display this without any problems. A problem occurs when I press the blur button, which runs some code to blur the image. The application becomes frozen and I get an OutOfMemoryException for a line of my code that creates a new array and stores this in another array in a nested for loop.
This is the code for the nested for loop:
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int xTranslated = (x + width / 2) % width;
int yTranslated = (y + height / 2) % height;
double real = temp[2 * (xTranslated + yTranslated * width)];
double imaginary = temp[2 * (xTranslated + yTranslated * width) + 1];
degradation[2 * (x + y * width)] = real;
degradation[2 * (x + y * width) + 1] = imaginary;
Complex c = new Complex(real, imaginary);
complex[y * width + x] = c;
}
}
This nested for loop deals with data extracted from the input image, which is stored as a Bitmap.
Here is the full method that applies the motion blur:
public Complex[] motionBlur(double[] degradation, int width, int height, double alpha, double gamma, double sigma) {
Complex[] complex = new Complex[width * height];
double[] temp = new double[2 * width * height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
double teta = Math.PI * ( (((x - width/2) % width) * gamma) + ((((y - height/2) % height) * sigma) ));
Sinc sinc = new Sinc();
double real = (Math.cos(teta) * sinc.value(teta)) * alpha;
double imaginary = (Math.sin(teta) * sinc.value(teta)) * alpha;
Complex cConj = new Complex(real, imaginary).conjugate();
temp[2 * (x + y * width)] = cConj.getReal();
temp[2 * (x + y * width) + 1] = cConj.getImaginary();
}
}
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int xTranslated = (x + width / 2) % width;
int yTranslated = (y + height / 2) % height;
double real = temp[2 * (xTranslated + yTranslated * width)];
double imaginary = temp[2 * (xTranslated + yTranslated * width) + 1];
degradation[2 * (x + y * width)] = real;
degradation[2 * (x + y * width) + 1] = imaginary;
Complex c = new Complex(real, imaginary);
complex[y * width + x] = c;
}
}
return complex;
}
Here is a link to what is being output by the logcat when I try to run the application: http://pastebin.com/ysbN9A3s
MainActivity.java:373 corresponds to the line,
Complex c = new Complex(real, imaginary);
Here is nice talk about android crashes.
Pierre-Yves talks about OOM (OutOfMemory error) at the time 11:39. So the problem in OOM is not place where OOM happens. You should profile your app to find the place where most memory is consumed. I should admit that OOM is one of the hardest error to resolve.
Good luck!
I'm in a tremendous bind with a last minute request on a consulting project I'm working on.
Essentially here is what I am trying to accomplish:
I have a surfaceview that draws a series of randomly sized circles. Each circle can have a radius from 50-100.
The x,y values are randomly generated along with a random radius
Each circle is created as an object representing that circle (x, y coord's and radius) and it is added to a list.
Once they are all created they are drawn.
The problem is I want to make sure none of these circles overlap.
I'm struggling a bit. This seems like it's shouldn't be all that difficult but it is for me unfortunately.
Here's my code so far (I know it's not close...be kind):
x = 100 + (int) (Math.random() * (mCanvasWidth - 200));
y = 100 + (int) (Math.random() * (mCanvasHeight - 200));
radius = 50 + (int) (Math.random() * 99);
color[0] = (float) (Math.random() * 360);
color[1] = 1;
color[2] = 1;
String radVal = String.valueOf(radius);
circle circ = new circle(x, y, radius, Color.HSVToColor(128, color), radVal);
boolean addit = true;
for (dot d : Dots) {
int leftSide = d.get_x() - radius;
int rightSide = d.get_x() + radius;
int xBoundary = x + radius;
int yBoundary = y + radius;
int exist_xLeft = d.get_x() - d.get_radius();
int exist_xRight = d.get_x() + d.get_radius();
int exist_yTop = d.get_y() - d.get_radius();
int exist_yBottom = d.get_y() + d.get_radius();
if ((xBoundary > exist_xLeft) && (xBoundary < exist_xRight))
{
if (yBoundary > (exist_yTop) && (yBoundary < exist_yBottom)) {
addit = false;
break;
}
}
}
if (addit)
circles.add(mdot);
if (circles.size() >= 5)
running = false;
Then it iterates the circles list and draws them to the canvas.
Any suggestions on where I'm failing in the collision detection?
You can detect if 2 circles are colliding like this:
Given:
centerpoints cx1,cy1 & cx2,cy2
and given radii r1 & r2,
Then you can determine if the 2 circles are colliding:
areColliding=((cx2-cx1)*(cx2-cx1)+(cy2-cy1)*(cy2-cy1))<((r1+r2)*(r1+r2));
If I have two points gather from onClick and they come as indexes or positions on the grid, how can I calculate weather to go up, down, left and right, diagonals are not allowed for the shortest route to the other point? So if i have pointA and pointB and point B is trying to get to pointA in the shortest path and I would recalculate this after every movement because pointA will move after movment from point B. What I have started to write is to find the adjacent positions around pointB without diagonals so points that are on edge will have less options obviously but how do I determine right movement with choices of neighboring squares? Should pointB go up,down,left and down preferably using indexes? I'm indexing from zero and its 11 by 11 grid so 11 columns. Something I just thought of is deal with choices that have the same distance, to select at random between them.
0 1 2 3 4 ...
11 12 13 14 15 ...
22 23 24 25 16 ...
33 34 35 36 37 ...
etc...
I find array of indexes that I now can try to pick for the shortest path
Integer[] getAdjacentPositions(int position)
{
/*This will return integer array of positions that adjacent to position that is
pass through that are not diagonal.*/
Integer[] columnRow = new Integer[8];
int columns = 11;
int column = (position % columns);
int row = (position / columns);
int numberedges = 0;
Log.d(TAG, "position inside of isedgeitem is " + position );
Log.d(TAG, "row is " + row );
Log.d(TAG, "column is " + column );
for (int rowOffset = -1; rowOffset <= 1; rowOffset++)
{
final int actRow = row + rowOffset;
for (int columnOffset = -1; columnOffset <= 1; columnOffset++)
{
final int actColumn = column + columnOffset;
if (actRow >= 0 && actRow < 11 && actColumn >= 0 && actColumn < 11)
{
if (!isOneOfDiagonals(position, (actColumn + actRow * columns)))
{
columnRow[numberedges]= actColumn + actRow * columns;
numberedges++;
}
Log.d(TAG, " actColumn" + actColumn );
Log.d(TAG, " actRow" + actRow );
}
}
}
return columnRow;
}
Now what to do with this array of Int Indexes to find the shortest path
shortestnextposition(Integer[] positions, int pointA )
{
return int position;
}
If I understand correctly the problem:
Difference between X positions of A and B : dX = Math.abs(ax - bx)
Difference between Y positions of A and B : dY = Math.abs(ay - by)
The shortest distance is : dX + dY
The problem with the shortest path is you can have different ways which uses the number of moves shortest distance. But you can code a preference in this move, for example, if you have to go from 0 to 24, the shortest distance is 3 and you have 3 shortest possible ways:
[0,11,22,23]
[0,1,12,23]
[0,11,12,23]
I suppose you want to use the third possibility?
For that, compare dX and dY and move in the greater dimension, if dX > dY, move X, if dY > dX, moveY
Update : try this
public static int[] shortestPath(int x, int a, int b) {
int ax = a % x, ay = a / x, bx = b % x, by = b / x;
int[] path = new int[Math.abs(ax - bx) + Math.abs(ay - by) + 1];
for (int i = 0; i < path.length; i++)
path[i] = a = i == 0 ? a : getAdjacentInDirectionOf(x, a, b);
return path;
}
public static int getAdjacentInDirectionOf(int x, int a, int b) {
int ax = a % x, ay = a / x, bx = b % x, by = b / x;
int dx = Math.abs(ax - bx), dy = Math.abs(ay - by);
if (dx >= dy) return (int) (ax + Math.signum(bx - ax) + ay * x);
else return (int) (ax + (ay + Math.signum(by - ay)) * x);
}
Update : replace shortestPath() method from previous by this one to avoid first case
public static int[] shortestPath(int x, int a, int b) {
int ax = a % x, ay = a / x, bx = b % x, by = b / x;
int[] path = new int[Math.abs(ax - bx) + Math.abs(ay - by)];
for (int i = 0; i < path.length; i++)
path[i] = a = getAdjacentInDirectionOf(x, a, b);
return path;
}