I am working on a drawing app where the user can create a rectangle, a row of holes, a grid of holes, and polygons. Right now I have the functionality to move these objects by determining if the touch point is within the bounds of an object, updating the objects coordinates during a TouchMove action, and then redrawing the object (along with everything else drawn) with the updated coordinates. My next step is to implement rotation. So far I am able to get a rotation angle, use that to rotate the canvas when drawing the rotated object, and then restore the canvas so the other objects are drawn without an angle. This works perfectly. The problem comes when I try to move/rotate the rotated object. I store the objects rotation, but I don't update it's stored coordinates; So when I try to determine if the user has touched the rotated object it doesn't match up with what the user sees on their screen. What I need is to be able to either modify the objects coordinates or the touch coordinates to reflect the rotation. Is there a way to do this? Am I going about this all wrong?
Here's some snippets of my code:
This determines if a grid of circles has been touched:
//retrieve touch coordinates. Adjust for matrix transformations
float currX=(event.getX()-matrixValues[2])/matrixValues[0];
float currY=(event.getY()-matrixValues[5])/matrixValues[4];
//... skip other code for snippet
else if(drawObject.getDrawAction()=="array")
{
ArrayList <DrawAction> redrawArray=drawObject.getDrawArray();
if(drawMode=="remove")
{
//determine which hole in grid was touched. "Remove" it
for(int y=0; y<redrawArray.size();y++)
{
DrawAction arrayAction=redrawArray.get(y);
if(currX>(arrayAction.getDrawX()-arrayAction.getDrawRadius()) && currX<(arrayAction.getDrawX()+arrayAction.getDrawRadius()) && currY<(arrayAction.getDrawY()+arrayAction.getDrawRadius()) && currY>(arrayAction.getDrawY()-arrayAction.getDrawRadius()))
{
arrayAction.setRemoved(true);
//add undo object for this action
DrawAction undoRemove= new DrawAction("remove", arrayAction);
undoList.add(undoRemove);
//redraw objects with updated status
redrawObjects(false);
break outerloop;
}
}
}
else
{
//determine all coordinates within the grid. If we are within the grid, then we want to move the whole grid
float holeRadius=redrawArray.get(0).getDrawRadius();
float lowestX=redrawArray.get(0).getDrawX()-holeRadius;
float lowestY=redrawArray.get(0).getDrawY()-holeRadius;
float highestX=redrawArray.get(redrawArray.size()-1).getDrawX()+holeRadius;
float highestY=redrawArray.get(redrawArray.size()-1).getDrawY()+holeRadius;
if(currX>lowestX && currX<highestX && currY>lowestY && currY<highestY)
{
touchObject=drawObject;
//store coordinates for new coordinate calculations
touchedX=currX;
touchedY=currY;
break outerloop;
}
}
}
this snippet is how I determine the angle:
touchObject.setRotationAngle((float) getDegreesFromTouchEvent(currX, currY));
touchObject.setRotated(true);
this is the function that returns the angle:
//determine rotation from touch event and screen dimensions
private double getDegreesFromTouchEvent(float x, float y){
double delta_x = x - (screenWidth) /2;
double delta_y = (screenHeight) /2 - y;
double radians = Math.atan2(delta_y, delta_x);
return (-1)*Math.toDegrees(radians);
}
and here's where I redraw everything after movement/rotation:
//redraw everything
for(int x=0; x<undoList.size();x++)
{
//retrieve next object to draw
DrawAction drawObject=undoList.get(x);
//retrieve object's brush width/paint color
this.setBrushSize(drawObject.getBrushWidth());
drawPaint.setColor(drawObject.getPaintColor());
//save state of canvas. This is so we can rotate it, draw, and then rotate back to its original state
drawCanvas.save();
//if this object has been rotated, then we need to rotate the canvas before drawing it
if(drawObject.isRotated())
{
drawCanvas.rotate(drawObject.getRotationAngle(),drawObject.getCenterX(),drawObject.getCenterY());
}
if(drawObject.getDrawAction()=="circle" && !drawObject.isRemoved())
{
drawCanvas.drawCircle(drawObject.getDrawX(), drawObject.getDrawY(), drawObject.getDrawRadius(),drawPaint);
}
if(drawObject.getDrawAction()=="rectangle")
{
if(!drawObject.isRemoved())
{
drawCanvas.drawRect(drawObject.getDrawLeft(), drawObject.getDrawTop(), drawObject.getDrawRight(), drawObject.getDrawBottom(),drawObject.getDrawPaint());
drawCanvas.drawCircle(drawObject.getCenterX(), drawObject.getCenterY(), 2, drawObject.getDrawPaint());
}
}
if(drawObject.getDrawAction()=="text" || drawObject.getDrawAction()=="delay")
{
drawCanvas.drawText(drawObject.getDrawtext(), drawObject.getDrawX(), drawObject.getDrawY(), drawObject.getDrawPaint());
}
if(drawObject.getDrawAction()=="array")
{
ArrayList <DrawAction> redrawArray=drawObject.getDrawArray();
for(int y=0; y<redrawArray.size();y++)
{
DrawAction arrayAction=redrawArray.get(y);
if(!arrayAction.isRemoved())
{
drawCanvas.drawCircle(arrayAction.getDrawX(), arrayAction.getDrawY(), arrayAction.getDrawRadius(),drawPaint);
}
}
}
if(drawObject.getDrawAction()=="path")
{
drawCanvas.drawPath(drawObject.getDrawPath(), drawPaint);
}
//restore canvas to original state
drawCanvas.restore();
}