CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Aug 2012
    Posts
    28

    [RESOLVED] Elliptical orbit

    I have a project, but i can make the square rotate around (circle), not that i want, i want the square rotate like Elipse, can you help me?
    Attached Files Attached Files

  2. #2
    Join Date
    Aug 2012
    Posts
    28

    Re: Elliptical orbit

    Someone help me, please!

  3. #3
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Elliptical orbit

    It would be much better if you explained your problem in more detail, and explained your code a bit, since your function names are not in English, so it's hard for those of us who don't speak your language to navigate around your source. You could have at least provided some comments.

    Anyway here you go - attached the modified project below.
    This is what I did: essentially, I stretched a circular path to create an elliptical one.

    I made some changes to your approach. In computer graphics, it's much better to keep the original data point as reference, untransformed (always at their original) location, and then get a new set of points on each frame by applying a transformation to the originals. So, I abandoned your 1deg-by-1deg transformation, and introduced additional set of points specifically for drawing, so that the original points don't have to change. Then I maintain an angle variable, which I update on your timer tick, by some increment (but I also keep it in the [0, 2Pi) range, once it's over 2Pi).

    This is the important bit. I first calculate point - center, which effectively puts the center at the origin (0, 0), to make the calculations simpler. Then I basically use your rotation code, without the second part of the equation related to the center point. This rotates the square figure, and it's points trace a circle. (Note that you could have used matrices for this - .Net comes with a 2D transform matrix capabilities, see: Matrix class, in the System.Drawing.Drawing2D namespace).
    After I rotate the point, I simply translate its Y-component by (ellipse_radius1 - ellipse_radius2) * sin(angle), which squashes (or stretches) the circular path vertically, into an ellipse. This is because when the angle is horizontal sin(0deg) = sin(180deg) = 0, and when the angle is vertical sin(90deg) = -sin(270deg) = 1.
    Once that's done, I show you how to rotate the elliptical path itself: you simply need to apply the rotate transformation one more tme, but this time using the pathAngle as the current angle.
    Finally, since all this was done about the origin, I translate the whole thing back to the center point (or rotation anchor point, if you will).

    Code:
            private PointF XoayDiemTamC(PointF p, PointF c, double a, double pathAngle)
            {
                PointF Q = new PointF();
    
                // position vector = point - center; (puts the center at the origin)
                Q = PointF.Subtract(p, new SizeF(c));
    
                // don't transform if p = c
                if ((-0.0001 < Q.X && Q.X < 0.0001) && (-0.0001 < Q.Y && Q.Y < 0.0001))  // Q.X == 0 && Q.Y == 0 might not work for floats
                    return p;
    
                // path location (on a circle)
                p.X = Q.X * (float)Math.Cos(a) - Q.Y * (float)Math.Sin(a);
                p.Y = Q.X * (float)Math.Sin(a) + Q.Y * (float)Math.Cos(a);
    
                p.Y -= (c_radius1 - c_radius2) * (float)Math.Sin(a);  // scales the circle vertically to make an ellipse
    
                // rotates the path itself
                float x = p.X;
                float y = p.Y;
                p.X = x * (float)Math.Cos(pathAngle) - y * (float)Math.Sin(pathAngle);
                p.Y = x * (float)Math.Sin(pathAngle) + y * (float)Math.Cos(pathAngle);
    
                // translate back to center
                p = PointF.Add(p, new SizeF(c));
                            
                return p;
            }
    I also slightly reorganized your code, added some constants, and made use of the Main_Paint handler, so as to eliminate flicker, draw the elliptical path, etc...

    P.S. PointF is a struct (that is, a value type), which means that it's passed around by value (a copy is made). So when you pass one to a method, changing the properties of the parameter will not affect the original point, since it's a copy (unless the method uses the ref keyword).
    Attached Files Attached Files
    Last edited by TheGreatCthulhu; August 7th, 2012 at 09:26 PM.

  4. #4
    Join Date
    Aug 2012
    Posts
    28

    Re: Elliptical orbit

    Quote Originally Posted by TheGreatCthulhu View Post
    It would be much better if you explained your problem in more detail, and explained your code a bit, since your function names are not in English, so it's hard for those of us who don't speak your language to navigate around your source. You could have at least provided some comments.

    Anyway here you go - attached the modified project below.
    This is what I did: essentially, I stretched a circular path to create an elliptical one.

    I made some changes to your approach. In computer graphics, it's much better to keep the original data point as reference, untransformed (always at their original) location, and then get a new set of points on each frame by applying a transformation to the originals. So, I abandoned your 1deg-by-1deg transformation, and introduced additional set of points specifically for drawing, so that the original points don't have to change. Then I maintain an angle variable, which I update on your timer tick, by some increment (but I also keep it in the [0, 2Pi) range, once it's over 2Pi).

    This is the important bit. I first calculate point - center, which effectively puts the center at the origin (0, 0), to make the calculations simpler. Then I basically use your rotation code, without the second part of the equation related to the center point. This rotates the square figure, and it's points trace a circle. (Note that you could have used matrices for this - .Net comes with a 2D transform matrix capabilities, see: Matrix class, in the System.Drawing.Drawing2D namespace).
    After I rotate the point, I simply translate its Y-component by (ellipse_radius1 - ellipse_radius2) * sin(angle), which squashes (or stretches) the circular path vertically, into an ellipse. This is because when the angle is horizontal sin(0deg) = sin(180deg) = 0, and when the angle is vertical sin(90deg) = -sin(270deg) = 1.
    Once that's done, I show you how to rotate the elliptical path itself: you simply need to apply the rotate transformation one more tme, but this time using the pathAngle as the current angle.
    Finally, since all this was done about the origin, I translate the whole thing back to the center point (or rotation anchor point, if you will).

    Code:
            private PointF XoayDiemTamC(PointF p, PointF c, double a, double pathAngle)
            {
                PointF Q = new PointF();
    
                // position vector = point - center; (puts the center at the origin)
                Q = PointF.Subtract(p, new SizeF(c));
    
                // don't transform if p = c
                if ((-0.0001 < Q.X && Q.X < 0.0001) && (-0.0001 < Q.Y && Q.Y < 0.0001))  // Q.X == 0 && Q.Y == 0 might not work for floats
                    return p;
    
                // path location (on a circle)
                p.X = Q.X * (float)Math.Cos(a) - Q.Y * (float)Math.Sin(a);
                p.Y = Q.X * (float)Math.Sin(a) + Q.Y * (float)Math.Cos(a);
    
                p.Y -= (c_radius1 - c_radius2) * (float)Math.Sin(a);  // scales the circle vertically to make an ellipse
    
                // rotates the path itself
                float x = p.X;
                float y = p.Y;
                p.X = x * (float)Math.Cos(pathAngle) - y * (float)Math.Sin(pathAngle);
                p.Y = x * (float)Math.Sin(pathAngle) + y * (float)Math.Cos(pathAngle);
    
                // translate back to center
                p = PointF.Add(p, new SizeF(c));
                            
                return p;
            }
    I also slightly reorganized your code, added some constants, and made use of the Main_Paint handler, so as to eliminate flicker, draw the elliptical path, etc...

    P.S. PointF is a struct (that is, a value type), which means that it's passed around by value (a copy is made). So when you pass one to a method, changing the properties of the parameter will not affect the original point, since it's a copy (unless the method uses the ref keyword).
    The first, i'm so sorry if my post wrong forum'rules, i'm sorry guy, i will learn what you say.
    So, thank you, very very and gratefull, i love this forum, i will visit more, so more. Thank guy again,

  5. #5
    Join Date
    Jan 2010
    Posts
    1,133

    Re: [RESOLVED] Elliptical orbit

    BTW, I just wanted to add that to get the elliptical path itself, you don't have to use
    p.Y -= (c_radius1 - c_radius2) * (float)Math.Sin(a)

    you can simply multiply the Y-component with a scale factor:
    p.Y = p.Y * c_radius2/c_radius1 //---(where c_radius2/c_radius1 < 1)

    But this only works to get the location on the path. in your case, since you're transforming all the points, this will squash the square figure itself, as well as the circle. What you can do is to define the square separately, in so-called object-space, rotate it there by the appropriate amount, and than translate it's "pivot point" to the location on the ellipse, in world-space. Another potential problem is that the square figure orients itself as if it was still on a circular path, which is the most apparent when the eccentricity is high. You can get the normal vector to a point on an ellipse made from a vertically squashed circle by stretching the same circle, along with the appropriate radius vector by the same amount (c_radius1/c_radius2), and then normalizing the radius vector.
    Once normalized, than sin(figureAngle) = normal.Y, and cos(figureAngle) = normal.X.

    So if:
    circle:
    x = cos(a);
    y = sin(a);

    ellipse:
    x = circle.x;
    y = circle.y * c_radius2/c_radius1;

    Then:
    normal:
    x = circle.x;
    y = circle.y * c_radius1/c_radius2;

    or:

    x = circle.x * c_radius2/c_radius1;;
    y = circle.y * c_radius1/c_radius2 * c_radius2/c_radius1;

    x = circle.x * c_radius2/c_radius1;
    y = circle.y;

    normal = normalize(normal);

  6. #6
    Join Date
    Aug 2012
    Posts
    28

    Re: [RESOLVED] Elliptical orbit

    Quote Originally Posted by TheGreatCthulhu View Post
    BTW, I just wanted to add that to get the elliptical path itself, you don't have to use
    p.Y -= (c_radius1 - c_radius2) * (float)Math.Sin(a)

    you can simply multiply the Y-component with a scale factor:
    p.Y = p.Y * c_radius2/c_radius1 //---(where c_radius2/c_radius1 < 1)

    But this only works to get the location on the path. in your case, since you're transforming all the points, this will squash the square figure itself, as well as the circle. What you can do is to define the square separately, in so-called object-space, rotate it there by the appropriate amount, and than translate it's "pivot point" to the location on the ellipse, in world-space. Another potential problem is that the square figure orients itself as if it was still on a circular path, which is the most apparent when the eccentricity is high. You can get the normal vector to a point on an ellipse made from a vertically squashed circle by stretching the same circle, along with the appropriate radius vector by the same amount (c_radius1/c_radius2), and then normalizing the radius vector.
    Once normalized, than sin(figureAngle) = normal.Y, and cos(figureAngle) = normal.X.

    So if:
    circle:
    x = cos(a);
    y = sin(a);

    ellipse:
    x = circle.x;
    y = circle.y * c_radius2/c_radius1;

    Then:
    normal:
    x = circle.x;
    y = circle.y * c_radius1/c_radius2;

    or:

    x = circle.x * c_radius2/c_radius1;;
    y = circle.y * c_radius1/c_radius2 * c_radius2/c_radius1;

    x = circle.x * c_radius2/c_radius1;
    y = circle.y;

    normal = normalize(normal);
    Yes, thank you, very very, i will learn

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured