2010-06-23 3 views
1

J'ai une réponse partielle. A partir de:Maths question sur la rotation des points dans .Net

newHeight = Taille * cos (radians) + Largeur * sin (radians)
newWidth = Taille * sin (radians) + Largeur * cos (radians)

Je peux inverser les équations pour obtenir :

temp = SQR (cos (radians)) - SQR (sin (radians))
Hauteur = newHeight * cos (radians) - newWidth * sin (radians)/Temp
width = NewWidth * cos (radians) - newHeight * sin (radians)/temp

Les équations ci-dessus ne se comportent que pour les plages d'angles 0-28, 62-90, 180-208 et 242-270. Hors de ces plages, les limites calculées sont trop grandes et entraînent un débordement à 45, 135, 225 et 315.
Je suppose que je dois détecter le quadrant dans lequel je suis et modifier légèrement les équations. Des idées?


J'ai eu du mal à être clair sur ce qu'est exactement ce que je demande dans cette question si nous espérons l'exemple suivant effacera les choses.
L'exemple prend un carré de 100x100, le fait pivoter de 12 degrés et ajoute 100 à la largeur. Qu'est-ce que je veux faire est de trouver les dimensions d'un rectangle qui, après avoir tourné de 12 degrés se traduira par le même rectangle, sans ajouter les 100 à la largeur après:

Les rectangles dessinés sont les limites de la forme en rotation et non la forme elle-même:

Dim radAngle = Math.PI * 12/180.0R 
    Dim widthChange = 100 

    Dim b2 = New RectangleF(200, 200, 100, 100) 
    b2 = GetBoundsAfterRotation(b2, radAngle) 
    b2.Width += widthChange 
    g.DrawRectangle(Pens.Red, ToRectangle(b2)) 

    Dim offsetY = 21 
    Dim offsetX = -7 
    b2 = New RectangleF(200, 200, 100 + widthChange - offsetX, 100 - offsetY) 
    b2 = GetBoundsAfterRotation(b2, radAngle) 
    b2.X += CInt(offsetX/2) 
    b2.Y += CInt(offsetY/2) 
    g.DrawRectangle(Pens.Green, ToRectangle(b2)) 

par piste et erreur je trouve les valeurs de offsetX et offsetY qui se traduiront dans le même rectangle pour ce cas particulier: a tourné 100x100 carré de 12 degrés avec 100 ajouté à la largeur . Je suis sûr que cela implique le péché, cos ou les deux quelque part mais le gel du cerveau m'empêche de construire la formule. ETA: Dans ce cas j'augmente la largeur, mais j'ai besoin d'une solution générale pour la largeur, la hauteur ou les deux changements. ETA2: Dans ce cas, la taille du rectangle résultant était de 218,6 x 118,6. Pour obtenir ces limites après la rotation par 12 degrés, les limites du rectangle de départ étaient d'environ 207 x 79.


Original:

J'utilise les éléments suivants, standard, routines pour obtenir les limites d'une image après a été tourné d'un angle spécifié, autour de son centre.Les limites sont décalées de sorte que le centre de l'image est toujours au même endroit:

Public Function GetBoundsAfterRotation(ByVal imageBounds As RectangleF, ByVal radAngle As Double) As RectangleF 

    Dim w = imageBounds.Width 
    Dim h = imageBounds.Height 
    Dim rotationPoints As PointF() = {New PointF(0, 0), New PointF(w, 0), New PointF(0, h), New PointF(w, h)} 
    RotatePoints(rotationPoints, New PointF(w/2.0F, h/2.0F), radAngle) 
    Dim newBounds = GetBoundsF(rotationPoints) 
    Dim x = imageBounds.X + newBounds.X //Offset the location to ensure the centre point remains the same 
    Dim y = imageBounds.Y + newBounds.Y 
    Return New RectangleF(New PointF(x, y), newBounds.Size) 

End Function 

//

Public Shared Sub RotatePoints(ByVal pnts As PointF(), ByVal origin As PointF, ByVal radAngle As Double) 
    For i As Integer = 0 To pnts.Length - 1 
     pnts(i) = RotatePoint(pnts(i), origin, radAngle) 
    Next 
End Sub 

//

Public Shared Function RotatePoint(ByVal pnt As PointF, ByVal origin As PointF, ByVal radAngle As Double) As PointF 
    Dim newPoint As New PointF() 
    Dim deltaX As Double = pnt.X - origin.X 
    Dim deltaY As Double = pnt.Y - origin.Y 
    newPoint.X = CSng((origin.X + (Math.Cos(radAngle) * deltaX - Math.Sin(radAngle) * deltaY))) 
    newPoint.Y = CSng((origin.Y + (Math.Sin(radAngle) * deltaX + Math.Cos(radAngle) * deltaY))) 
    Return newPoint 
End Function 

//

Public Shared Function GetBoundsF(ByVal pnts As PointF()) As RectangleF 
    Dim left As Single = pnts(0).X 
    Dim right As Single = pnts(0).X 
    Dim top As Single = pnts(0).Y 
    Dim bottom As Single = pnts(0).Y 

    For i As Integer = 1 To pnts.Length - 1 
     If pnts(i).X < left Then 
      left = pnts(i).X 
     ElseIf pnts(i).X > right Then 
      right = pnts(i).X 
     End If 

     If pnts(i).Y < top Then 
      top = pnts(i).Y 
     ElseIf pnts(i).Y > bottom Then 
      bottom = pnts(i).Y 
     End If 
    Next 

    Return New RectangleF(left, top, CSng(Math.Abs(right - left)), CSng(Math.Abs(bottom - top))) 
End Function 

Ma question est:

J'ai quelques BoundsAfterRotation qui ont été tournés d'un angle autour de son centre. Je change la largeur et/ou la hauteur des limites. Comment puis-je travailler en arrière pour trouver les images originales qui auraient créé le BoundsAfterRotation?

+0

Je ne comprends pas votre question c'est une question purement mathématique AFAIK. Pouvez-vous reformuler votre question avec seulement du vocabulaire mathématique? Vous pouvez également consulter: http://en.wikipedia.org/wiki/Rotation_matrix – mathk

+0

Connaissez-vous toujours l'angle? – Jens

+0

@ mathk, C'est une question purement mathématique. Si j'ai un carré et le fais pivoter d'un angle puis augmente la largeur de W, je veux savoir combien la largeur et l'emplacement du carré original (pré-rotation) ont changé. Cela va, selon l'angle, être différent de W. – Jules

Répondre

1

Il suffit de le faire revenir en arrière avec le même angle, négatif. Notez que vous pourriez envisager d'utiliser la classe System.Drawing.Matrix. Il a une méthode RotateAt(). Utilisez la méthode TransformPoints() pour appliquer la rotation. Et la méthode Invert() pour créer une matrice qui recense les points.

+0

Cela fonctionnera-t-il? Je serais surpris. Je vais essayer plus tard. Je dois aller voir l'Angleterre, je l'espère, ne pas être éliminé de la coupe du monde! – Jules

0

Vous pouvez passer de l'image à la rotation, mais pas de la rotation à l'image. C'est parce que lorsque vous faites pivoter, vous devez arrondir les positions des pixels et la nouvelle image semble un peu différente.

Par conséquent, vous devez toujours conserver l'image originale et faire des copies de l'image pour chaque roation.

Le simple retour en arrière doublera l'arrondi.

+0

Je garde l'image originale. Voir mon commentaire à mathk ci-dessus, et j'espère que cela clarifie exactement ce que j'essaie de faire. – Jules

0

Je n'ai pas le temps de donner une réponse complète, mais considérons ce qui suit: Si vous commencez par le carré tourné par pi/2, de sorte qu'il ressemble à <>, et soit alpha l'angle entre la ligne reliant le centre du carré avec son bord le plus à droite et l'axe des x, alors la trigonométrie assez basique vous dit, que la largeur du carré tourné est cos(alpha)*d, avec d étant la diagonale du carré, si alpha est entre -pi/4 et pi/4. Maintenant, il vous suffit de calculer l'alpha à partir de votre angle, de vérifier quels bords sont importants pour connaître la largeur et de calculer la largeur "non orientée" de la diagonale.

+0

Salut, cela semble prometteur. Y a-t-il une équation similaire qui relie la nouvelle hauteur à alpha et d ?. Si j'ai ceci, alors j'ai assez d'informations pour calculer la largeur de départ et la hauteur requises. Merci. – Jules

+0

J'ai trouvé une autre équation, et j'ai presque une réponse. J'ai modifié ma question pour montrer ce que j'ai jusqu'ici. – Jules