problema de rotação de forma personalizada

Eu estou tentando girar uma forma personalizada em torno de seu centro, mas não consigo obter o resultado conforme o esperado.

o que eu quero é

*forma deve ser girada em torno de seu centro sem se mover.*

o que a minha solução está fazendo atualmente égirando uma forma inteira em torno de seu centro, por cada rotação está mudando sua posição.

Eu tenho várias formas, então eu criei uma classe para encapsular uma forma com sua transformação na seguinte classe

public abstract class Shoe implements Shape, ShoeShape {

    // variable declaration

    /**
     * 
     */
    public Shoe() {
        position = new Point();
        lastPosition = new Point();
    }




    public void draw(Graphics2D g2, AffineTransform transform, boolean firstTime) {

        AffineTransform af = firstTime ? getInitTransform()
                : getCompositeTransform();

        if (af != null) {


                Shape s = af.createTransformedShape(this);

                if (getFillColor() != null) {
                    g2.setColor(getFillColor());
                    g2.fill(s);
                } else {
                    g2.draw(s);
                }
            }

        }



    }




    public AffineTransform getCompositeTransform() {
            AffineTransform af = new AffineTransform();
        af.setToIdentity();
        af.translate(position.getX(), position.getY());
        Point2D centerP = calculateShapeCenter();
        af.rotate(orientation, centerP.getX(), centerP.getY());
        return af;
    }







    public void onMouseDrag(MouseEvent me, Rectangle2D canvasBoundary,
            int selectionOperation) {

        // shape operation can be either resize , rotate , translate ,
        switch (selectionOperation) {
        case MmgShoeViewer.SHAPE_OPERATION_MOVE:
            // MOVEMENT
            break;
        case MmgShoeViewer.SHAPE_OPERATION_ROTATE:

            Point2D origin = calculateShapeCenter();
            Point2D.Double starting = new Point2D.Double(me.getX(), me.getY());
            currentAngle = RotationHelper.getAngle(origin, starting);
            rotationAngle = currentAngle - startingAngle;
            rotate(rotationAngle);
            break;
        case MmgShoeViewer.SHAPE_OPERATION_RESIZE:
            break;
        default:
            System.out.println(" invalid select operation");
        }
    }



    public void onMousePress(MouseEvent me, Rectangle2D canvasBoundary,
            int selectionOperation) {

        // shape operation can be either resize , rotate , translate ,
        switch (selectionOperation) {
        case MmgShoeViewer.SHAPE_OPERATION_MOVE:
            break;
        case MmgShoeViewer.SHAPE_OPERATION_ROTATE:
            Point2D origin =  calculateShapeCenter();
            Point2D.Double starting = new Point2D.Double(me.getX(), me.getY());
            startingAngle = RotationHelper.getAngle(origin, starting);
            setShapeOperation(selectionOperation);
            break;
        case MmgShoeViewer.SHAPE_OPERATION_RESIZE:
            break;
        default:
            System.out.println(" invalid select operation");
        }
    }

    public void onMouseRelease(MouseEvent me, Rectangle2D canvasBoundary,
            int selectionOperation) {

        // shape operation can be either resize , rotate , translate ,
        switch (selectionOperation) {
        case MmgShoeViewer.SHAPE_OPERATION_MOVE:
            break;
        case MmgShoeViewer.SHAPE_OPERATION_ROTATE:
            // FIXME rotation angle computation
            setShapeOperation(-1);
            break;
        case MmgShoeViewer.SHAPE_OPERATION_RESIZE:
            break;
        default:
            System.out.println(" invalid select operation");
        }
    }

    public void rotate(double angle) {
        orientation = (float) angle;
    }


    public void translate(double deltaX, double deltaY) {

        position.setLocation(deltaX, deltaY);
        lastPosition.setLocation(deltaX, deltaY);
    }







    // another getter and setter

Eu estou calculando o ângulo de rotação usando o seguinte método

public static double getAngle(Point2D origin, Point2D other) {

        double dy = other.getY() - origin.getY();
        double dx = other.getX() - origin.getX();
        double angle;

        if (dx == 0) {// special case
            angle = dy >= 0 ? Math.PI / 2 : -Math.PI / 2;
        } else {
            angle = Math.atan(dy / dx);
            if (dx < 0) // hemisphere correction
                angle += Math.PI;
        }
        // all between 0 and 2PI
        if (angle < 0) // between -PI/2 and 0
            angle += 2 * Math.PI;
        return angle;
    }

no evento de imprensa do mouse do ouvinte mouse de tela

selectedShape.onMousePress(me, canvasBoundary, shoeViewer
                .getShapeOperation());

Eu estou apenas chamando o método onMousePress da forma selecionada

e no meu método de arrastar do mouse do ouvinte do mouse de tela, estou apenas chamando o método onMouseDrag da forma selecionada que atualiza o ângulo de rotação como você pode ver desde a primeira classe

selectedShape.onMouseDrag(me, canvasBoundary, shoeViewer
                .getShapeOperation());

e você pode ver o método de desenhar da forma individual, para desenhar a forma de acordo com a transformação atual, estou chamando de paintComponent como

Iterator<Shoe> shoeIter = shoeShapeMap.values().iterator();

        while (shoeIter.hasNext()) {

            Shoe shoe = shoeIter.next();
            shoe.draw(g2, firstTime);

        }

Em que shoeShapeMap contém todas as formas personalizadas atualmente na tela.

estou cometendo erro no cálculo do ângulo ou na determinação do ponto de ancoragem? minha solução atual gira 360 graus verificando todas as condições [90 graus etc.] como você pode ver no método acima mencionado.

Eu quero que a forma deve ser girada em torno de seu centro sem redimensionar suas posições? na palavra é difícil de explicar, então, por favor, sugira-me alguma maneira melhor de mostrar aqui o que eu quero realizar?

Acho que mencionei todas as coisas relacionadas a esse problema. Se você tiver alguma dúvida, por favor, não hesite em me perguntar.

Encontrei 2 posts relacionados aqui, mas não consegui encontrar muita informação deles.

questionAnswers(1)

yourAnswerToTheQuestion