I have created custom image view for remove a selected part from bitmap images.
There are operation for select area to get rid from current bitmap by a path has a collection of points.
Here it is code snippet :
for (int i = points.size() - 2; i < points.size(); i++) {
if (i >= 0) {
Point point = points.get(i);
if (i == 0) {
Point next = points.get(i + 1);
point.dx = ((next.x - point.x) / 3);
point.dy = ((next.y - point.y) / 3);
} else if (i == points.size() - 1) {
Point prev = points.get(i - 1);
point.dx = ((point.x - prev.x) / 3);
point.dy = ((point.y - prev.y) / 3);
} else {
Point next = points.get(i + 1);
Point prev = points.get(i - 1);
point.dx = ((next.x - prev.x) / 3);
point.dy = ((next.y - prev.y) / 3);
}
}
}
path.cubicTo(prev.x + prev.dx, prev.y + prev.dy, point.x - point.dx,
point.y - point.dy, point.x, point.y);
paramCanvas.drawPath(path, paint);
Look at this output:
I used clip path to get crop this part but this not working for me.
I am getting stuck to clip that selected part so can you help me out to solve this thing.
I would greatly appreciated any help. Thanks
Related
I am using Google Map API to get lines on the map in my application. I am loading the nodes of the lines from a database using following code:
// Add polyline "walks voda"
List<WalkLine> dbwalknodes = dbclass.queryWalksFromDatabase(this); // list of latlng
for (int i = 0; i < dbwalknodes.size() - 1 ; i++) {
WalkLine source = dbwalknodes.get(i);
WalkLine destination = dbwalknodes.get(i+1);
Polyline line = mMap.addPolyline(new PolylineOptions()
.add(new LatLng(source.getLat(), source.getLon()),
new LatLng(destination.getLat(), destination.getLon()))
.width(16)
.color(Color.parseColor("#1b9e77"))
.geodesic(true));
line.setZIndex(1000);
}
Do you have any idea how to create the lines smoother while it bends than on the picture bellow? Is it possible?
https://www.dropbox.com/s/6waic988mj90kdk/2014-10-22%2012.48.04.png?dl=0
You should not create a polyline for each two points, it should be a connected polyline with mulitple points, something like this:
public void drawRoute(List<LatLng> location) {
polylineOptions = new PolylineOptions().width(MAPS_PATH_WIDTH).color(routeColor).addAll(location);
polyLine = map.addPolyline(destinationRoutePolyLineOptions);
polyLine.setPoints(location);
}
This will make it much smoother.
Use the following code based on bSpline algorithm, it worked for me on Android.
public List<LatLng> bspline(List<LatLng> poly) {
if (poly.get(0).latitude != poly.get(poly.size()-1).latitude || poly.get(0).longitude != poly.get(poly.size()-1).longitude){
poly.add(new LatLng(poly.get(0).latitude,poly.get(0).longitude));
}
else{
poly.remove(poly.size()-1);
}
poly.add(0,new LatLng(poly.get(poly.size()-1).latitude,poly.get(poly.size()-1).longitude));
poly.add(new LatLng(poly.get(1).latitude,poly.get(1).longitude));
Double[] lats = new Double[poly.size()];
Double[] lons = new Double[poly.size()];
for (int i=0;i<poly.size();i++){
lats[i] = poly.get(i).latitude;
lons[i] = poly.get(i).longitude;
}
double ax, ay, bx, by, cx, cy, dx, dy, lat, lon;
float t;
int i;
List<LatLng> points = new ArrayList<>();
// For every point
for (i = 2; i < lats.length - 2; i++) {
for (t = 0; t < 1; t += 0.2) {
ax = (-lats[i - 2] + 3 * lats[i - 1] - 3 * lats[i] + lats[i + 1]) / 6;
ay = (-lons[i - 2] + 3 * lons[i - 1] - 3 * lons[i] + lons[i + 1]) / 6;
bx = (lats[i - 2] - 2 * lats[i - 1] + lats[i]) / 2;
by = (lons[i - 2] - 2 * lons[i - 1] + lons[i]) / 2;
cx = (-lats[i - 2] + lats[i]) / 2;
cy = (-lons[i - 2] + lons[i]) / 2;
dx = (lats[i - 2] + 4 * lats[i - 1] + lats[i]) / 6;
dy = (lons[i - 2] + 4 * lons[i - 1] + lons[i]) / 6;
lat = ax * Math.pow(t + 0.1, 3) + bx * Math.pow(t + 0.1, 2) + cx * (t + 0.1) + dx;
lon = ay * Math.pow(t + 0.1, 3) + by * Math.pow(t + 0.1, 2) + cy * (t + 0.1) + dy;
points.add(new LatLng(lat, lon));
}
}
return points;
}
I have a problem of finding the angle of three points with mouse pointer. The rotation doesn't following the mouse as the mouse move around the rotating object.
This is my formula :
double degree = Math.toDegrees( Math.atan2(
(now.y - point.y) - (previous.y - point.y),
(now.x - point.x) - (previous.x - point.x)));
Log.w("RESULT", "DEGREE = " + degree);
if ( degree < 0 )
degree = 360 - (-degree);
This last 2 line was added later.
This is the full code of tracking the mouse rotation.
Camera camera = Camera.getInstance();
if (event.getActionMasked() == MotionEvent.ACTION_DOWN &&
event.getPointerCount() == 1) {
previous = new Point(event.getX(), event.getY());
previous = camera.getMapPoint(previous);
}
else if (event.getActionMasked() == MotionEvent.ACTION_MOVE &&
event.getPointerCount() == 1)
{
Point now = new Point(event.getX(), event.getY());
now = camera.getMapPoint(now);
ArrayList<GameObject> list = mObject.getSubObjects();
GameObject part = list.get(0);
Point point = part.getPolygon().getCenter();
Log.w("RESULT", "Previous = " + previous.x + " " + previous.y);
Log.w("RESULT", "Next = " + now.x + " " + now.y);
Log.w("RESULT", "Center = " + point.x + " " + now.y);
double degree = Math.toDegrees( Math.atan2(
(now.y - point.y) - (previous.y - point.y),
(now.x - point.x) - (previous.x - point.x)));
Log.w("RESULT", "DEGREE = " + degree);
if ( degree < 0 )
degree = 360 - (-degree);
android.graphics.Matrix matrix = new android.graphics.Matrix();
matrix.postRotate((float) degree, point.x, point.y);
// Polygon polygon;
// Polygon.Builder builder = new Polygon.Builder();
for (int i=0; i<part.getPolygon().getVertex().size(); i++)
{
float[] newPoint = new float[2];
Point p = part.getPolygon().getVertex().get(i);
newPoint[0] = p.x;
newPoint[1] = p.y;
matrix.mapPoints(newPoint);
part.getPolygon().getVertex().remove(i);
part.getPolygon().getVertex().add(i, new Point(newPoint[0], newPoint[1]));
}
previous = new Point(event.getX(), event.getY());
previous = camera.getMapPoint(previous);
}
else if (event.getActionMasked() == MotionEvent.ACTION_UP)
{
previous = null;
isSelected = false;
}
If you want to find angle between vectors (point-previous) and (point-now), use:
Math.atan2((now.x - point.x)*(previous.y - point.y) -
(now.y - point.y)*(previous.x - point.x),
(now.x - point.x)*(now.y - point.y) -
(previous.x - point.x)*(previous.y - point.y))
(This is atan2(vectorproduct, scalarproduct))
You may also use
angle = atan2(now.y-point.y, now.y-point.y)-
atan2(previous.y-point.y, previous.x-point.x);
I have a few problems with time in my game. Play my game (link won't post all code) to 50 points ... the tubes stay closed .. why?
The tubes only open in the game if a bird spawns, why? The tubes are actually only 1 sec to be getting, do I have something wrong in the code?
The file in which I place the most important is code: SquishyBird/SquishyBird/src/com/CoreTek/squishybird/GameScreen.java
Seondly,
how can I set a Delay when you touched at the background: touched -> door close -> 1sec -> door opens
Wwhile this 1 sec the emenies at my game should still move, so it cant be a freeze delay. How can I do this?
Maybe the error is here:
delayTime = TimeUtils.millis();
if(Gdx.input.isTouched()){
Assets.rect_pipe_down.y = 512 - 320/2 - 96;
Assets.rect_pipe_up.y = -320 + 320/2 + 96;
Assets.rect_hitbox.x = 288/2 - 52/2 + 2;
}
if(TimeUtils.millis() - delayTime > 1000){
Assets.rect_pipe_down.y = 512 - 320/2;
Assets.rect_pipe_up.y = -320 + 320/2;
Assets.rect_hitbox.x = 288/2 - 52/2 + 2 + 500;
}
My whole rendering:
#Override
public void render(float delta){
Gdx.gl.glClearColor(0F, 0F, 0F, 1F);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
stateTime += Gdx.graphics.getDeltaTime();
Assets.region_current_bird = Assets.animation_bird.getKeyFrame(stateTime, true);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(Assets.region_bg, 0, 0);
batch.draw(Assets.region_pipe_down, Assets.rect_pipe_down.x, Assets.rect_pipe_down.y);
batch.draw(Assets.region_pipe_up, Assets.rect_pipe_up.x, Assets.rect_pipe_up.y);
Assets.font_points.draw(batch, "Points: " + String.valueOf(points), 10, 512 - 10);
for(Rectangle rect_bird: Assets.rect_birds_array){
batch.draw(Assets.region_current_bird, rect_bird.x, rect_bird.y);
}
batch.end();
if(Gdx.input.isTouched()){
Assets.rect_pipe_down.y = 512 - 320/2 - 96;
Assets.rect_pipe_up.y = -320 + 320/2 + 96;
Assets.rect_hitbox.x = 288/2 - 52/2 + 2;
}
if(TimeUtils.millis() - delayTime > 1000){
Assets.rect_pipe_down.y = 512 - 320/2;
Assets.rect_pipe_up.y = -320 + 320/2;
Assets.rect_hitbox.x = 288/2 - 52/2 + 2 + 500;
}
if(TimeUtils.millis() - lastSpawnTime > spawnTime) spawnBirds();
Iterator<Rectangle> iter = Assets.rect_birds_array.iterator();
while(iter.hasNext()){
Rectangle bird = iter.next();
bird.x += 200 * Gdx.graphics.getDeltaTime();
if(bird.x - 34 > 288) iter.remove();
if(bird.overlaps(Assets.rect_hitbox)){
points++;
if(spawnTime > 10){
spawnTime-=10;
}
iter.remove();
}
}
}
problem on calculation of x coordinate for plotting on iPhone screen.When points are within the range of 300 meter we are getting all the point of interest closer even-though In actual they are spread.I have even changed the width of the viewPort from 0.5 to 0.17(In degrees converted 28.647889757 to 10.0).Can anyone suggest such that every points of interest are properly placed with respect to the actual position.
The standard way(Mixare,ARToolkit) of calculating points on AR is
Calculate using ARKit
double pointAzimuth = coordinate.coordinateAzimuth;
//our x numbers are left based.
double leftAzimuth = self.currentCoordinate.coordinateAzimuth - VIEWPORT_WIDTH_RADIANS / 2.0;
if (leftAzimuth < 0.0) {
leftAzimuth = 2 * M_PI + leftAzimuth;
}
if (pointAzimuth < leftAzimuth) {
//it's past the 0 point.
point.x = ((2 * M_PI - leftAzimuth + pointAzimuth) / VIEWPORT_WIDTH_RADIANS) * 480.0;
} else {
point.x = ((pointAzimuth - leftAzimuth) / VIEWPORT_WIDTH_RADIANS) * 480.0;
}
IN Mixare:
CGPoint point;
CGRect viewBounds = self.overlayView.bounds;
//NSLog(#"pointForCoordinate: viewBounds.size.width = %.3f, height = %.3f", viewBounds.size.width, viewBounds.size.height );
double currentAzimuth = self.currentCoordinate.coordinateAzimuth;
double pointAzimuth = coordinate.coordinateAzimuth;
//NSLog(#"pointForCoordinate: location = %#, pointAzimuth = %.3f, pointInclination = %.3f, currentAzimuth = %.3f", coordinate.coordinateTitle, point.x, point.y, radiansToDegrees(pointAzimuth), radiansToDegrees(currentAzimuth), radiansToDegrees(pointInclination) );
double deltaAzimuth = [self deltaAzimuthForCoordinate:coordinate];
BOOL isBetweenNorth = [self isNorthForCoordinate:coordinate];
//NSLog(#"pointForCoordinate: (1) currentAzimuth = %.3f, pointAzimuth = %.3f, isNorth = %d", radiansToDegrees(currentAzimuth), radiansToDegrees(pointAzimuth), isBetweenNorth );
// NSLog(#"pointForCoordinate: deltaAzimuth = %.3f", radiansToDegrees(deltaAzimuth));
//NSLog(#"pointForCoordinate: (2) currentAzimuth = %.3f, pointAzimuth = %.3f, isNorth = %d", radiansToDegrees(currentAzimuth), radiansToDegrees(pointAzimuth), isBetweenNorth );
if ((pointAzimuth > currentAzimuth && !isBetweenNorth) ||
(currentAzimuth > degreesToRadians(360-self.viewRange) &&
pointAzimuth < degreesToRadians(self.viewRange))) {
// Right side of Azimuth
point.x = (viewBounds.size.width / 2) + ((deltaAzimuth / degreesToRadians(1)) * 12);
} else {
// Left side of Azimuth
point.x = (viewBounds.size.width / 2) - ((deltaAzimuth / degreesToRadians(1)) * 12);
}
I want to fill the color in white area for Paint based application
so please give me suggestion for how to do this work..
I found the Solution with Flood fill algoritham
private void FloodFill(Bitmap bmp, Point pt, int targetColor, int replacementColor){
Queue<Point> q = new LinkedList<Point>();
q.add(pt);
while (q.size() > 0) {
Point n = q.poll();
if (bmp.getPixel(n.x, n.y) != targetColor)
continue;
Point w = n, e = new Point(n.x + 1, n.y);
while ((w.x > 0) && (bmp.getPixel(w.x, w.y) == targetColor)) {
bmp.setPixel(w.x, w.y, replacementColor);
if ((w.y > 0) && (bmp.getPixel(w.x, w.y - 1) == targetColor))
q.add(new Point(w.x, w.y - 1));
if ((w.y < bmp.getHeight() - 1)
&& (bmp.getPixel(w.x, w.y + 1) == targetColor))
q.add(new Point(w.x, w.y + 1));
w.x--;
}
while ((e.x < bmp.getWidth() - 1)
&& (bmp.getPixel(e.x, e.y) == targetColor)) {
bmp.setPixel(e.x, e.y, replacementColor);
if ((e.y > 0) && (bmp.getPixel(e.x, e.y - 1) == targetColor))
q.add(new Point(e.x, e.y - 1));
if ((e.y < bmp.getHeight() - 1)
&& (bmp.getPixel(e.x, e.y + 1) == targetColor))
q.add(new Point(e.x, e.y + 1));
e.x++;
}
}}
flood fill in android:
See this FloodFill
Here's a quick application using Python and OpenCV (should be available on Android if you try hard enough):
"""Flood fills with random color on click. Press `q' to exit."""
import cv
import sys
import random
TOL = 10
TOL_BGR = (TOL, TOL, TOL, 0)
def click(event,x,y,flags,im):
if event == cv.CV_EVENT_LBUTTONDOWN:
b,g,r = [ random.random() * 255 for i in range(3) ]
cv.FloodFill(im, (x,y), (b,g,r,0), TOL_BGR, TOL_BGR)
im = cv.LoadImage(sys.argv[1], cv.CV_LOAD_IMAGE_COLOR)
cv.NamedWindow(__file__, 1)
cv.SetMouseCallback(__file__, click, im)
while True:
cv.ShowImage(__file__, im)
key = cv.WaitKey(33)
if chr(key & 0xff) == 'q':
break
cv.SaveImage('floodfill.png', im)
Every time the user clicks an image, the application flood-fills using the click location as a seed. The color is picked randomly. You can change the tolerances by modifying the value of TOL (or TOL_BGR). Here's the result after a couple of clicks:
The general algorithm is the same regardless of what technology you use.
1)Have the Split up image for each color portion separately with same size as actual image and other portion are transparent.
2)Have the complete image with each portion painting in different color in ur drawable folder - this is just reference image.
3) Add the all split up images in frame layout and set all split up invisible initially and set visible to actual image only
4) Hot code the color for each split up from ur reference image (step2) for Eg handSplitImageColor = green;
4) Set the listener for frame layout find out the x and y position and pass the x and y position to ur reference image (step 2) and find out the color in that particular location and match the color with step 4 and fill the particular in that image and set the visibility true for that split up image. So only that portion will get filled by color since other portion are transparent.
These are the steps i used for one of my same type of problems.
But I don't think this is the better solution but it works well for me.
after lot of searching, i came up with the following.
It is fast and efficient
private void myFloodFillMethod(Point node,int targetColor, int fillColor) {
if (targetColor != fillColor) {
Queue<Point> queue = new LinkedList<>();
do {
int x = node.x;
int y = node.y;
while (x > 0 && getPixelColorFromArr(x - 1, y) == targetColor) {
x--; }
boolean spanUp = false;
boolean spanDown = false;
while (x < width && checkEquality(getPixelColorFromArr(x, y),targetColor)) {
setPixelColorFromArr(x, y, fillColor);
if (!spanUp && y > 0
&& checkEquality(getPixelColorFromArr(x, y - 1),targetColor)) {
queue.add(new Point(x, y - 1));
spanUp = true;
} else if (spanUp && y > 0
&& !checkEquality(getPixelColorFromArr(x, y - 1),targetColor)) {
spanUp = false;
}
if (!spanDown && y < height - 1
&& checkEquality(getPixelColorFromArr(x, y + 1), targetColor)) {
queue.add(new Point(x, y + 1));
spanDown = true;
} else if (spanDown && y < height - 1
&& !checkEquality(getPixelColorFromArr(x, y + 1),targetColor)) {
spanDown = false;
}
x++;
}
} while ((node = queue.poll()) != null);
}
}
private boolean checkEquality(int pixelColorFromArr, int targetColor) {
return pixelColorFromArr == targetColor;
}
void fillColorInImage(Bitmap image, Point node, int targetColor, int replacementColor){
if(targetColor == replacementColor) return;
width = image.getWidth();
height = image.getHeight();
pixelArr = new int[width*height];
image.getPixels(pixelArr,0,width,0,0,width,height);
myFloodFillMethod(node,targetColor,replacementColor);
image.setPixels(pixelArr,0,width,0,0,width,height);
}
how to call:
fillColorInImage(bmp, point, targetColor, replacementColor);
where
bmp is the bitmap of image(extract form the image view)
point is Point(x,y) where user has tapped:get it from event.getX() and event.getY()
targetColor is the color of the point: get it from bitmap.getPixel()
replacementColor is the color you want to replace it to