Question

J'ai une image avec deux points alignés comme suit:

|----------------|
|                |
|    .           |
|                |
|          .     |
|                |
|----------------|

J'ai les deux coordonnées X, Y pour les deux points et je dois faire pivoter l'image de X degrés pour qu'elle ressemble à ceci:

|----------------|
|                |
|                |
|    .     .     |
|                |
|                |
|----------------|

En gros, ils s’alignent côte à côte. Quel est le calcul pour cela? (Un exemple de code en C # serait encore mieux, mais pas obligatoire)

Était-ce utile?

La solution

Cela dépend du point que vous souhaitez utiliser comme "centre". pour votre rotation. Appelons le point vers le haut et le point gauche A et celui vers la droite et en dessous du point B. Si vous souhaitez faire pivoter le point A de sorte que le point B s’aligne sur lui, le calcul de l’angle de rotation en radians s’effectue comme suit:

double angle = Math.Atan2(pointB.Y - pointA.Y, pointB.X - pointA.X);

Je ne sais pas comment vous gérez votre image. Par conséquent, ce qui suit ne s'applique que si vous utilisez System.Drawing.Graphics:

myImage.TranslateTransform(-pointA.X, -pointA.Y);
myImage.RotateTransform((float) angle, MatrixOrder.Append);
myImage.TranslateTransform(pointA.X, pointA.Y, MatrixOrder.Append);

J'espère que ça aide.

Autres conseils

Pas de code, désolé, mais une stratégie.

Vous devez pouvoir créer l'image de résultat en échantillonnant l'image source. Vous connaissez l'angle de rotation. Vous devez donc maintenant créer une fonction de mappage qui mappe du résultat vers l'original.

Le code balayerait simplement chaque ligne de l'image résultante et mapperait le pixel sur l'image d'origine. Vous pouvez faire un simple;

for (int plotY = 0; plotY < resultHeight; plotY++)
{
   for (int plotX = 0; plotX < resultWidth; plotX++)
   {
         resultImage.PlotPixel(getOriginalPixel(plotX, plotY, angleOfRotation));
   } 
}

Nous avons donc besoin de la magie "getOriginalPixel" " méthode, et c’est là que les maths entrent en jeu.

Si nous faisons pivoter l'image de 0 degré, alors plotX, plotY ne représente que le X / Y de l'image d'origine. Mais ce n'est pas amusant.

pickX = x * cos(angle) - y * sin(angle)
pickY = y * cos(angle) + x * sin(angle)

Je pense que mappera au pixel source. Vous aurez besoin de vérifier si c'est hors de portée et juste de retourner noir ou quelque chose comme ça:)

Le code ci-dessous fonctionne

  Matrix mRotate = new Matrix();
    mRotate.Translate(Convert.ToInt32(Width.Value) / -2, Convert.ToInt32(Height.Value) / -2, MatrixOrder.Append);
    mRotate.RotateAt(theta, new Point(0, 0), MatrixOrder.Append);

    using (GraphicsPath gp = new GraphicsPath())
    {  // transform image points by rotation matrix
        gp.AddPolygon(new Point[] { new Point(0, 0), new Point(Convert.ToInt32(Width.Value), 0), new Point(0, Convert.ToInt32(Height.Value)) });
        gp.Transform(mRotate);
        PointF[] pts = gp.PathPoints;

        // create destination bitmap sized to contain rotated source image
        Rectangle bbox = boundingBox(bmpSrc, mRotate);
        Bitmap bmpDest = new Bitmap(bbox.Width, bbox.Height);


        using (Graphics gDest = Graphics.FromImage(bmpDest))
        {  // draw source into dest


            Matrix mDest = new Matrix();
            mDest.Translate(bmpDest.Width / 2, bmpDest.Height / 2, MatrixOrder.Append);
            gDest.Transform = mDest;
            gDest.DrawImage(bmpSrc, pts);
            gDest.DrawRectangle(Pens.Transparent, bbox);
            //drawAxes(gDest, Color.Red, 0, 0, 1, 100, "");
            return bmpDest;
        }
    }

Recherchez d'abord le point central:

Point p = new Point((x1-x2)/2, (y1-y2)/2)

Utilisez ensuite la trigonométrie pour résoudre l’angle. Je vais supposer que nous avons redéfini l’origine sur notre point central; j’ai donc un nouveau x3 et un autre y3 sur l’un des points.

hypotenuse = SqrRt(x3^2 + y3^2)

Nous résolvons l'angle inconnu TH

Sin(TH) = opposite / hypotenuse

Donc, pour résoudre ce problème, il nous faut:

TH = Asin(y3 / hypotenuse)

Tourner par TH .

Voir Wikipedia pour la référence des fonctions trigonométriques

Pour effectuer une transformation 2D générale, il faut résoudre deux problèmes avec 6 inconnues.

'x = xA + yB + C

'y = xD + yE + D

Étant donné 3 points correspondants, vous aurez 6 connus et le système peut être résolu. Dans ce cas, vous ne disposez que de 4 points, puisque vous ne vous souciez pas du cisaillement, mais vous pouvez imaginer introduire un troisième point à 90 degrés de la ligne formée par les deux autres points. Créer une image pivotée est alors (pseudo-codé) quelque chose comme:

for ( y = 0; y < height; y++ )
 for ( x = 0; x < width; x++ )
  {
    newx = x*A + y*B + C;
    newy = x*D + y*D + E;
    newimage(x,y ) = oldimage( newx, newy );
  }
}

Si les performances sont importantes, les multiplications dans la boucle interne peuvent être optimisées en notant que y * B ne change que dans l'apparence extérieure et que newx, newy est modifié par les constantes A et D dans la boucle interne.

Vous devez consulter les matrices de rotation géométrique: Consultez ce site pour obtenir une explication détaillée

Toutefois, pour obtenir de meilleurs résultats, vous devez passer de la destination à la source, puis utiliser la transformation pour chaque pixel de destination:

m = rotation matrix

for each point p in destination
  p' = p.m
  get pixel p' from source
  set pixle p in destination

Il existe, dans les méthodes du framework .net, toutes ces solutions: System.Drawing.Graphics.RotateTransform et System.Drawing.Graphics.TranslateTransform . Vous devrez configurer une translation pour déplacer le point de rotation de l'image vers l'origine, puis appliquer la rotation puis une autre translation pour la ramener à la position d'origine. Vous devrez expérimenter ces fonctions pour déterminer leur comportement - je suis au travail pour le moment et je n'ai pas le temps de vous donner un code qui fonctionne. : - (

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top