Call an outstream bluetooth method from another class - java

I have a color picker palette class and i want to send the color information while the client changes the color ( OnTouch ) through the bluetooth class in separate java file. The bluetooth Fragment is working and connecting perfectly . The problem is that the write method is working in its class but when i initialize it and try to use it in the color palette class it crashes on the test.
The working write() method in the bluetooth class :
private int col;
public void write(int color) {
col=color;
if(socket.isConnected()) {
// data = "r " + Color.red(color) + "/n" + "g " + Color.green(color) + "/n" + "b " + Color.blue(color) + "/n";
try {
/* byte[] dataToSend = {(byte) r,(byte)Color.red(color),(byte)Color.green(color),(byte) Color.blue(color), 0x0A};
//remove spurious line endings from color bytes so the serial device doesn't get confused
for (int i=0; i<dataToSend.length-1; i++){
if (dataToSend[i] == 0x0A){
dataToSend[i] = 0x0B;
}
}*/
// mmOutStream.write(data.getBytes());
mmOutStream.write(("r " + Color.red(col) + '\n').getBytes());
mmOutStream.write(("g " + Color.green(col) + '\n').getBytes());
mmOutStream.write(("b " + Color.blue(col) + '\n').getBytes());
} catch (IOException e) {
}
}
else
{
Toast.makeText(getContext(),
String.format("Not connected."),
Toast.LENGTH_SHORT).show();
}
}
The way i am trying to use the method in the color palette class(ColorPicker.java) :
BluetoothFragment rat = new BluetoothFragment();
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
int x = (int) event.getX();
int y = (int) event.getY();
int cx = x - getWidth() / 2;
int cy = y - getHeight() / 2;
double d = Math.sqrt(cx * cx + cy * cy);
if (d <= colorWheelRadius) {
colorHSV[0] = (float) (Math.toDegrees(Math.atan2(cy, cx)) + 180f);
colorHSV[1] = Math.max(0f, Math.min(1f, (float) (d / colorWheelRadius)));
invalidate();
} else if (x >= getWidth() / 2 && d >= innerWheelRadius) {
colorHSV[2] = (float) Math.max(0, Math.min(1, Math.atan2(cy, cx) / Math.PI + 0.5f));
invalidate();
}
return true;
}
rat.write(getColor());
return super.onTouchEvent(event);
}

Related

Drawing a shape in processing

I was working on an animation on processing. Then, I have a question about the loop. Normally, my code is more long. However, I made a simple code which can usefull also for the beginners.
My sample code:
void setup(){
println("Line between points " + curr + " and " + (curr+1));
println("initial X: " + initialX + " initial Y: " + initialY );
println("final X: " + finalX + " final Y: " + finalY );
counter = 0; // reset counter;
}
void draw() {
point(initialX, initialY);
println(initialX, initialY, p);
}
So, like you see I used "Bresenhams Algorithm" for drawing the lines. However when I draw the lines it doesn't draw the lines between points. It's just drawing a little bit. Normally my text file is so long. How to I draw lines that can follow from first x and y coordinates to last x and y coordinates without disconnection?
This is implementation of a version of Bresenham's algorithm using balancing the positive and negative error between the x and y coordinates:
/*
String[] coordinates = { // Creating an array for my text file.
"117 191",
"96 223",
"85 251",
"77 291",
"78 323",
"84 351",
"97 378",
"116 404",
"141 430"
};
*/
int[][] points;
int deltaX, deltaY;
int initialX, initialY; // Initial point of first coodinate
int finalX, finalY; // Final point of first coodinate
int counter = 0;
int curr = 0;
int sx, sy, err;
void setup() {
size(500, 500);
strokeWeight(4);
frameRate(25);
coordinates = loadStrings("coordinates.txt");
beginShape(); // It combines the all of vertexes
points = new int[coordinates.length][2];
int row = 0;
for (String line : coordinates) {
String[] pair = line.split(" ");
points[row] = new int[] { Integer.parseInt(pair[0]), Integer.parseInt(pair[1])};
println(points[row][0]); // print x
println(points[row][1]); // print y
row++;
}
fixLines();
endShape(CLOSE);
}
void fixLines() {
int ix = curr % points.length;
int jx = (curr + 1) % points.length;
initialX = points[ix][0];
initialY = points[ix][1];
finalX = points[jx][0];
finalY = points[jx][1];
deltaX = abs(finalX - initialX);
sx = initialX < finalX ? 1: -1;
deltaY = -abs(finalY - initialY);
sy = initialY < finalY ? 1: -1;
err = deltaX + deltaY;
println("Line between points " + curr + " and " + (curr+1));
println("[" + initialX + ", " + initialY + "] - [" + finalX + ", " + finalY + "]");
println("deltaX=" + deltaX);
}
void draw() {
point(initialX, initialY);
if (initialX == finalX && initialY == finalY) {
curr++;
if (curr == points.length) {
noLoop();
} else {
fixLines();
}
} else {
int e2 = 2 * err;
if (e2 >= deltaY) {
err += deltaY;
initialX += sx;
}
if (e2 <= deltaX) {
err += deltaX;
initialY += sy;
}
}
}
The output is very close to linear implementation:
I try updating method draw to update deltaY and continue drawing until deltaY != 0 but result does not look good. Most likely you need to review your implementation of the algorithm and related calculations.
void draw()
{
point(initialX, initialY);
println(initialX, initialY, p);
if (finalX > initialX )
initialX++;
else
initialX--;
if (p < 0) {
p = p + 2 * deltaY;
} else {
if (initialY > finalY)
initialY--;
else
initialY++;
p = p + 2 * deltaY - 2 * deltaX;
}
deltaY = abs(finalY - initialY); // update deltaY
counter++;
if (counter > deltaX) {
if (deltaY > 0) {
counter--;
} else {
curr++;
if (curr == points.length) {
noLoop(); // possibly you should break out of the main loop here
} else {
fixLines();
}
}
}
}
Implementation with line(initialX, initialY, finalX, finalY); looks much better.
void draw()
{
point(initialX, initialY);
println(initialX, initialY, p);
line(initialX, initialY, finalX, finalY);
curr++;
if (curr == points.length) {
noLoop();
} else {
fixLines();
}
}

ImageView onTouch not moving up and down but only around circle

I am developing a joystick button. Everything is ok when moving it around circle, but when I want to move it up or down, it goes only around circle again from the right side. So, I want to have both options (to move up or down in circle like real joystick). Here is my code example. Thanks for any help
public class JoystickView extends FrameLayout implements View.OnTouchListener {
private Context context;
private ImageView backgroundImageView;
private ImageView buttonImageView;
private RelativeLayout relativeLayout;
private View rootView;
float xx = 0;
float yy = 0;
public JoystickView(Context context) {
super(context);
this.context = context;
setLayout(this);
buttonImageView.setOnTouchListener(this);
this.setClipChildren(false);
}
public void setLayout(ViewGroup view) {
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
View v = inflateControlerLayout();
view.addView(v, layoutParams);
}
protected View inflateControlerLayout() {
initSlider();
rootView = relativeLayout;
return rootView;
}
public void initSlider() {
if (relativeLayout == null) {
relativeLayout = new RelativeLayout(context);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
relativeLayout.setLayoutParams(layoutParams);
relativeLayout.setClipChildren(false);
}
if (backgroundImageView == null) {
backgroundImageView = new ImageView(context);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
backgroundImageView.setLayoutParams(layoutParams);
// load image
try {
// get input stream
InputStream ims = getContext().getAssets().open("joystick_background.png");
// load image as Drawable
Drawable d = Drawable.createFromStream(ims, null);
// set image to ImageView
backgroundImageView.setImageDrawable(d);
} catch (IOException ex) {
return;
}
}
if (buttonImageView == null) {
buttonImageView = new ImageView(context);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, Gravity.CENTER);
buttonImageView.setLayoutParams(layoutParams);
// load image
try {
// get input stream
InputStream ims2 = getContext().getAssets().open("jostick_button.png");
// load image as Drawable
Drawable d2 = Drawable.createFromStream(ims2, null);
// set image to ImageView
buttonImageView.setImageDrawable(d2);
buttonImageView.bringToFront();
} catch (IOException ex) {
return;
}
}
if (relativeLayout != null) {
relativeLayout.addView(backgroundImageView);
relativeLayout.addView(buttonImageView);
}
}
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_UP:
view.setX(xx);
view.setY(yy);
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
float cx = view.getWidth() / 2.f;
float cy = view.getHeight() / 2.f;
float x = motionEvent.getRawX();
float y = motionEvent.getRawY();
float w = buttonImageView.getWidth();
float h = buttonImageView.getHeight();
double r = Math.min(cx, cy) / 2.;
double dx = x - cx;
double dy = y - cy;
double hypot = Math.hypot(dx, dy);
double cos = dx / hypot;
double sin = dy / hypot;
double rdx = hypot < 1. ? 0. : r * cos;
double rdy = hypot < 1. ? 0. : r * sin;
buttonImageView.setTranslationX((float) (cx + rdx - w / 2.));
buttonImageView.setTranslationY((float) (cy + rdy - h / 2.));
break;
}
return true;
}
}
These lines constrain the coordinates to a circle (oval) path or center:
double rdx = hypot < 1. ? 0. : r * cos;
double rdy = hypot < 1. ? 0. : r * sin;
For hypot to be less than 1 (that's 1 pixel) you'd have to be dead center.
I changed it to only constrain the coordinates within the circle:
double rcos = r * cos;
double rsin = r * sin;
double rdx = Math.abs(dx) < Math.abs(rcos) ? dx : rcos;
double rdy = Math.abs(dy) < Math.abs(rsin) ? dy : rsin;
I think this might be what you want.
I have found a working solution if someone is looking for it
private Point calculate (float x, float y) {
float cx = buttonImageView.getWidth() / 2.f;
float cy = buttonImageView.getHeight() / 2.f;
double r = cx / 2.; // vrednost radius
double dx = x;
double dy = y;
double hypot = Math.hypot(dx, dy); // izracun hipotenuze
double cos = dx / hypot; // cos
double sin = dy / hypot; // sin
double rcos = r * cos;
double rsin = r * sin;
double rdx = Math.abs(dx) < Math.abs(rcos) ? dx : rcos; // if,else
double rdy = Math.abs(dy) < Math.abs(rsin) ? dy : rsin;
return new Point((int)rdx, (int)rdy);
}
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
final float x = motionEvent.getRawX(); // x točko
final float y = motionEvent.getRawY(); // y točka
//Log.d("VALUES", "RAW X:" + motionEvent.getRawX() + ", RAW Y:" + motionEvent.getRawY() + ", X:" + motionEvent.getX() + ", CX:" + cx + ", CY:" + cy + ", dx:" + dx + ", dy:" + dy + ", Hypo:" + hypot + ", cos:" + cos + ", sin" + sin);
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
xDelta = view.getX() - x;
yDelta = view.getY() - y;
break;
case MotionEvent.ACTION_UP:
doBounceAnimation(buttonImageView);
doVibration();
view.setX(xx);
view.setY(yy);
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
final float transX = (float) x;
final float transY = (float) y;
thread = new Thread() {
#Override
public void run() {
Point newPoint = calculate(transX+ xDelta,transY + yDelta);
buttonImageView.setX(newPoint.x);
buttonImageView.setY(newPoint.y);
}
};
thread.start();
Log.d(TRANSLATIONX,"X:" + transX + ", Y:" + transY);
break;
}
return true;
}
Enjoy coding!

Images are not resizing after dynamically adding Imageviews in relative layout

I am trying to create photo collage app. Here I am dynamically adding imageviews in relative layout by passing array of positions for creating grid. Grids are successfully created. But when I add images, the images aren't scaled properly or not fitting to entire imageview's area. Also when I add touch listener on images, images are moviing outside the area of imageview.Please help me in this.Thanks in advance Here is my code
public void drawGrids() {
Resources res = getResources();
int Rid = c.id;
TypedArray ta = res.obtainTypedArray(Rid);
int n = ta.length();
String[][] array = new String[n][];
for (int i = 0; i < n; ++i) {
int id = ta.getResourceId(i, 0);
if (id > 0) {
array[i] = res.getStringArray(id);
Log.e(" array", "" + i + " " + Arrays.toString(array[i]));
String[] values = Arrays.toString(array[i]).replaceAll("[\\[\\]\\s]", "").split(","); // extracting each element from array
final int position = i;
limit = position+1;
float x = Float.parseFloat(values[0]);
float y = Float.parseFloat(values[1]);
float w = Float.parseFloat(values[2]);
float h = Float.parseFloat(values[3]);
Log.e(" x:", "" + x);
Log.e(" y:", "" + y);
Log.e(" w:", "" + w);
Log.e(" h:", "" + h);
img1 = new ImageView(getActivity());
img1.setImageResource(R.drawable.button_background);
params = new RelativeLayout.LayoutParams((int) ((Screen_width * w) - padding), (int) ((Screen_height * h) - padding));
// x= x* Screen_width
// y= y* Screen_height
params.leftMargin = (int) ((Screen_width * x) + padding);
params.topMargin = (int) ((Screen_height * y) + padding);
params.rightMargin = padding;
params.bottomMargin = padding;
Log.e(" px(x):", "" + (int) (Screen_width * x));
Log.e(" px(y):", "" + (int) (Screen_height * y));
Log.e(" px(w):", "" + (int) (Screen_width * w));
Log.e("px(h)", "" + (int) (Screen_height * h));
if(!mSelectedImages.isEmpty()) {
onPickedSuccessfully(mSelectedImages);
}
else {
img1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("clicked", "" + position);
onClickPickImageMultipleWithLimit(img1);
}
});
}
IMGS.add(img1); // arraylist of imageview
root1.addView(img1, params);
createPreview();
} else {
// something wrong with the XML
}
}
ta.recycle();
}
public void onPickedSuccessfully(ArrayList<ImageEntry> images) { // selected images path are to be fetched here
mSelectedImages = images;
handler.post(new Runnable() {
#Override
public void run() {
for (j = 0; j <IMGS.size(); j++) {
final ImageView child=IMGS.get(j);
child.onTouchListener(new MultiTouchListener);// multitouch listener for zooming and scrolling picked image
Log.e("w n h", "" + child.getWidth() + " " + child.getHeight());
int areaheight = child.getWidth();
int areawidth = child.getHeight();
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
oldBitmap = BitmapFactory.decodeFile(String.valueOf(mSelectedImages.get(j)), bmOptions);//decodeFile(String.valueOf(mSelectedImages.get(j)));
int height = oldBitmap.getHeight(), width = oldBitmap.getWidth();
Log.e(" b width and height ", "" + oldBitmap.getWidth() + " " + oldBitmap.getHeight());
Log.e(" area width and height ", "" + areawidth + " " + areaheight);
Bitmap scaledBitmap;
if (areaheight > areawidth) {
// portrait
float ratio = (float) height / areaheight;
height = areaheight;
width = (int) (width / ratio);
scaledBitmap = Bitmap.createScaledBitmap(oldBitmap, width, height, true);
Log.e("porait scaled w ht ", "" + scaledBitmap.getWidth() + " " + scaledBitmap.getHeight());
} else if (areawidth > areaheight) {
//landscape
float ratio = (float) width / areawidth;
width = areawidth;
height = (int) (height / ratio);
scaledBitmap = Bitmap.createScaledBitmap(oldBitmap, width, height, true);
Log.e("landscape scaled w ht ", "" + scaledBitmap.getWidth() + " " + scaledBitmap.getHeight());
} else {
// square
height = areaheight;
width = areawidth;
scaledBitmap = Bitmap.createScaledBitmap(oldBitmap, width, height, true);
Log.e("square scaled w ht ", "" + scaledBitmap.getWidth() + " " + scaledBitmap.getHeight());
}
child.setImageBitmap(scaledBitmap);
}
}
});
In your case you need to add line:
img1.setScaleType(ImageView.ScaleType.CENTER_CROP); // or CENTER_INSIDE, or FIT_CENTER, or for example FIT_XY
after:
img1.setImageResource(R.drawable.button_background);
Thus, you will provide scaling for all images that will be set into your ImageView. You can read more about scaleType here and here
Rather than use ImageView and setOnTouchListener, you may try this custom view.
public class ScaleImageView extends ImageView {
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.0f;
private float x = 0;
private float y = 0;
private float tx = 0;
private float ty = 0;
private float dx = 0;
private float dy = 0;
private int scrollLimitX = 0;
private int scrollLimitY = 0;
private boolean justScaled = false;
public ScaleImageView(Context context) {
super(context);
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
public ScaleImageView(Context context, AttributeSet attrs) {
super(context, attrs);
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent ev) {
if(ev.getPointerCount() == 1){
switch(ev.getAction()){
case MotionEvent.ACTION_DOWN:
tx = ev.getX();
ty = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if(!justScaled){
dx = tx - ev.getX();
dy = ty - ev.getY();
tx -= dx;
ty -= dy;
int scrollX = (int)(this.getScrollX()/mScaleFactor);
int scrollY = (int)(this.getScrollY()/mScaleFactor);
if(Math.abs(scrollX+dx) > scrollLimitX) dx = 0;
if(Math.abs(scrollY+dy) > scrollLimitY) dy = 0;
this.scrollBy((int)(dx*mScaleFactor), (int)(dy*mScaleFactor));
}
break;
case MotionEvent.ACTION_UP:
justScaled = false;
break;
}
}else if(ev.getPointerCount() == 2){
justScaled = true;
mScaleDetector.onTouchEvent(ev);
}
return super.onTouchEvent(ev);
}
#Override
public void onDraw(Canvas canvas) {
x = this.getWidth()/2;
y = this.getHeight()/2;
canvas.scale(mScaleFactor, mScaleFactor, x ,y);
int scrollX = (int)(this.getScrollX()/mScaleFactor);
int scrollY = (int)(this.getScrollY()/mScaleFactor);
if(Math.abs(scrollX) > scrollLimitX) dx = scrollLimitX - scrollX; else dx = 0;
if(Math.abs(scrollY) > scrollLimitY) dy = scrollLimitY - scrollY; else dy = 0;
this.scrollBy((int)(dx*mScaleFactor), (int)(dy*mScaleFactor));
super.onDraw(canvas);
}
public void setScaleFactor(float mfactor){
this.mScaleFactor = mfactor;
}
public float getScaleFactor(){
return this.mScaleFactor;
}
public void setScrollLimit(int x, int y){
this.scrollLimitX = x/2;
this.scrollLimitY = y/2;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 5.0f));
ScaleImageView.this.invalidate();
return true;
}
}
}
To limit the image that at least one corner is inside the view:
// zoomImg is the Bitmap.
// mZoomImage is the ScaleImageView.
float scaleFactor = Math.min((float)(mZoomImage.getWidth())/zoomImg.getWidth(), (float)(mZoomImage.getHeight())/zoomImg.getHeight());
mZoomImage.setScrollLimit((int)(zoomImg.getWidth()*scaleFactor), (int)(zoomImg.getHeight()*scaleFactor));
Hope this is helpful!

Translations between screen co-ordinates and image co-ordinates after scaling and zooming

I have a class that manages translating from screen co-ordinates to image co-ordinates.
However, I have an "off by one error".
The following gives 318, 198, instead of 319, 199:
#Test
public void test6rightScreenCornerToImageCoOrdAfterZoomingAndScaling() {
PointTranslation pointTranslation = new PointTranslation();
pointTranslation.setOriginalSize(0, 0, 320, 200); // original image
pointTranslation.zoomIn(9, 9, 310, 190); // zoomed image starting at 9,9
pointTranslation.scale(0, 0, 800, 800);
Point translatedPoint = pointTranslation.transformPoint(799,799);
System.out.println(testName.getMethodName() + " : " + translatedPoint.toString());
assertTrue(translatedPoint.x == 319);
assertTrue(translatedPoint.y == 199);
}
=============================================================
Full Listing:
package gtx;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.internal.gdip.PointF;
import org.eclipse.swt.internal.gdip.RectF;
#SuppressWarnings("restriction")
public class PointTranslation {
RectF originalSize = null;
RectF currentSize = null;
RectF scaledSize = null;
public void setOriginalSize(int originX, int originY, int width, int height) {
originalSize = getRectangle(originX, originY, width, height);
currentSize = originalSize;
}
public void zoomIn(int originX, int originY, int width, int height) {
// System.out.println("addTranslation: " + originX + " " + originY + " "
// + width + " " + height);
currentSize = getRectangle(originX, originY, width, height);
}
public void scale(int originX, int originY, int width, int height) {
// System.out.println("addTranslation: " + originX + " " + originY + " "
// + width + " " + height);
scaledSize = getRectangle(originX, originY, width, height);
}
public boolean isPointWithinBounds(Point point) {
return isPointWithinBounds(point.x, point.y);
}
public boolean isPointWithinBounds(int xPos, int yPos) {
boolean ret = false;
if (scaledSize != null) {
RectF sourceRec = scaledSize;
int xBounds = (int) (sourceRec.Width + sourceRec.X);
int yBounds = (int) (sourceRec.Height + sourceRec.Y);
ret = (xPos < xBounds) && (yPos < yBounds) && (xPos > sourceRec.X) && (yPos > sourceRec.Y);
}
return ret;
}
public Point transformPoint(Point point) {
return transformPoint(point.x, point.y);
}
public Point transformPoint(int xPos, int yPos) {
Point sourcePoint = new Point((int) xPos, (int) yPos);
Point retPoint = sourcePoint;
if (this.scaledSize != null) {
retPoint = transformPoint(this.scaledSize, this.currentSize, sourcePoint);
}
return retPoint;
}
/*
* Rectangle 1 has (x1, y1) origin and (w1, h1) for width and height, and
* Rectangle 2 has (x2, y2) origin and (w2, h2) for width and height, then
*
* Given point (x, y) in terms of Rectangle 1 co-ords, to convert it to
* Rectangle 2 co-ords: xNew = ((x-x1)/w1)*w2 + x2; yNew = ((y-y1)/h1)*h2 +
* y2;
*/
private Point transformPoint(RectF source, RectF destination, Point intPoint) {
PointF point = new PointF();
point.X = intPoint.x;
point.Y = intPoint.y;
return transformPoint(source, destination, point);
}
private Point transformPoint(RectF source, RectF destination, PointF point) {
return new Point((int) ((((point.X - source.X) / source.Width) * destination.Width + destination.X)),
(int) ((((point.Y - source.Y) / source.Height) * destination.Height + destination.Y)));
}
private RectF getRectangle(int x, int y, int width, int height) {
RectF rect = new RectF();
rect.X = x;
rect.Y = y;
rect.Height = height;
rect.Width = width;
return rect;
}
private PointF getPoint(int x, int y) {
PointF retPoint = new PointF();
retPoint.X = x;
retPoint.Y = y;
return retPoint;
}
public void reset() {
this.originalSize = null;
this.currentSize = null;
this.scaledSize = null;
}
}
Update:
My issue definitely seems to be with rounding. Its strange, for some test cases I need to Round Up to get the correct Point, and sometimes I need to round Up. I am missing something like a scaling factor or something. Any suggestions how to the Translation between two Rectangles correctly?
Update 2:
I tried the following method, but with still no joy:
private Point transformPoint(RectF source, RectF destination, PointF point) {
float xPercent = normalize(point.X,source.X,source.Width);
float destX = xPercent*(Math.abs(destination.Width - destination.X)) + destination.X;
float yPercent = normalize(point.Y,source.Y,source.Height);
float destY = yPercent*(Math.abs(destination.Height - destination.Y)) + destination.Y;
System.out.println("Float x,y: " + destX + ", " + destY);
System.out.println("Ceil Float x,y: " + Math.floor(destX) + ", " + Math.floor(destY) );
return new Point((int)Math.floor(destX), (int)Math.floor(destY));
}
private float normalize(float value, float min, float max) {
return Math.abs((value - min) / (max - min));
}
In running the test case and stepping through the code, my debugging shows the following substitutions...
transformPoint(RectF source, RectF destination, PointF point) {
return new Point (
(int) (((( 799 - 0 ) / 800 ) * 310 ) + 9 )),
(int) (((( 799 - 0 ) / 800 ) * 190 ) + 9 ))
);
}
The first half of the equation returns 318.6125. The second half of the equation returns 198.7625.
You need to either
modify the equation so that the int transformation truncates to the
desired value (such as + 1 at the end)
round up before conversion to int
live with the result
And as Mathew noted, multiple translations in a row distort and magnify the problem, much like averaging averages.
As stated by Reenactor, you need to round points before conversion to int:
private Point transformPoint(RectF source, RectF destination, PointF point) {
final int ptx = Math.round((((point.X - source.X) / source.Width) * destination.Width + destination.X));
final int pty = Math.round((((point.Y - source.Y) / source.Height) * destination.Height + destination.Y));
return new Point(ptx, pty);
}
Is it possible you are converting the interim results after each translation to integer points?
Remember, org.eclipse.swt.graphics.Point stores x and y as int, so any fractions in your calculations are dropped.
That is:
1) First translation:
x1 = ((799 - 0) / 800) * 301 + 9 = 309.62375
y1 = ((799 - 0) / 800) * 181 + 9 = 189.77375
If you were storing those in a Point object before going into the next translation, they would be truncated to (309, 189) and you would get
2) Second translation
x2 = ((309 - 9) / 301) * 320 + 0 = 318.93...
y2 = ((189 - 9) / 181) * 200 + 0 = 198.89...
Which would, in turn, be truncated to (318, 198).

Moving through a tilemap; gets stuck vertically when it hit the middle of the map

So I'm making a simple game where I have a tilemap (or cellmap depending on your terminology). The problem is: if I have a map over about 100 tiles if I move about halfway down the map the app will move me to the last row(meaning the bottom row on screen is the last row) and I can no longer move up but have no trouble moving horizontally. I would really appreciate it if someone could tell me what I'm doing wrong and why what I'm doing doesn't work for anything above ~100 tilesThe code for moving.
Here's the code showing how I handle the touch events. If you think you need more code be sure to tell me.
#Override
public boolean onTouchEvent(MotionEvent event) {
// touch down
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// new event
_isMoving = false;
// store coordinates
_xTouch = (int) event.getX();
_yTouch = (int) event.getY();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
_isMoving = true;
// new offset
_xOffSet += _xTouch - (int) event.getX();
_yOffSet += _yTouch - (int) event.getY();
// make sure it never goes out of bounds
if (_xOffSet < 0) {
_xOffSet = 0;
} else if (_xOffSet > _mapSize * _cellSize - getWidth()) {
_xOffSet = _mapSize * _cellSize - getWidth();
}
if (_yOffSet < 0) {
_yOffSet = 0;
} else if (_yOffSet > getHeight()) {
_yOffSet = _mapSize * _cellSize - getHeight();
}
_xTouch = (int) event.getX();
_yTouch = (int) event.getY();
findMapEnds();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
// touch released
if (!_isMoving) {
int column = (int) FloatMath.ceil((_xOffSet + event.getX())
/ _cellSize) - 1;
int row = (int) FloatMath.ceil((_yOffSet + event.getY())
/ _cellSize) - 1;
Cell cell = _mapCells.get(row).get(column);
Toast.makeText(getContext(), "Cell id #" + cell.get_id(),
Toast.LENGTH_SHORT).show();
}
}
return true;
}
private void findMapEnds() {
// finds the map end.
_StartRow = _yOffSet / _cellSize;
_MaxRow = (int) Math.min(_mapSize, _StartRow + Math.floor(getHeight())
/ _cellSize + 2);
_StartCol = _xOffSet / _cellSize;
_MaxCol = (int) Math.min(_mapSize, _StartCol + Math.floor(getWidth())
/ _cellSize + 2);
_XScrollOffset = (int) (((_xOffSet / (float) _cellSize) - (_xOffSet / _cellSize)) * _cellSize);
_YScrollOffset = (int) (((_yOffSet / (float) _cellSize) - (_yOffSet / _cellSize)) * _cellSize);
}

Categories