Click here to Skip to main content
15,887,946 members
Home / Discussions / Algorithms
   

Algorithms

 
AnswerRe: Filling a cylinder or a tube Pin
Moreno Airoldi21-Mar-10 0:08
Moreno Airoldi21-Mar-10 0:08 
GeneralRe: Filling a cylinder or a tube Pin
Valeriant21-Mar-10 4:46
Valeriant21-Mar-10 4:46 
GeneralRe: Filling a cylinder or a tube Pin
Moreno Airoldi21-Mar-10 8:33
Moreno Airoldi21-Mar-10 8:33 
GeneralRe: Filling a cylinder or a tube Pin
Valeriant21-Mar-10 16:36
Valeriant21-Mar-10 16:36 
GeneralRe: Filling a cylinder or a tube Pin
Moreno Airoldi25-Mar-10 2:06
Moreno Airoldi25-Mar-10 2:06 
GeneralRe: Filling a cylinder or a tube Pin
Valeriant25-Mar-10 19:34
Valeriant25-Mar-10 19:34 
GeneralRe: Filling a cylinder or a tube Pin
Moreno Airoldi25-Mar-10 22:24
Moreno Airoldi25-Mar-10 22:24 
GeneralRe: Filling a cylinder or a tube Pin
Moreno Airoldi2-Apr-10 23:02
Moreno Airoldi2-Apr-10 23:02 
Ok I took some time to go through my code and try to give you some idea as how to get a filled cylinder. Sorry I didn't look at your code (guess I'm just too lazy hehe), but I think this one should help you.

I tried to do some cleanup, but be aware that my code is still not that polished.

I did some experiments on the track I first suggested you: using the angle to get the outer points for both ellipses. This simple version works just fine, except for rotation angles not in the range from -10 to +10 degrees you'll need to compensate (i.e. add an offset to the angles 0 and PI I'm using here to get the outer points):

C#
private void FillEllipse(Graphics g, Color line_color, Color fill_color, double center_x, double center_y, double semi_minor, double semi_major, double angle)
{
    // *** Pens and brushes ***
    Pen mypen = new Pen(line_color);
    SolidBrush mybrush = new SolidBrush(fill_color);

    // *** Constants ***
    double PI2 = Math.PI * 2;

    // *** Rotation angle in radians, sine and cosine ***
    double beta = -angle * (Math.PI / 180);
    double sin_beta = Math.Sin(beta);
    double cos_beta = Math.Cos(beta);

    // *** Calculate increment by a rough estimation of the number of points needed (empirical!) ***
    double increment = (Math.PI * 2) / (semi_major * 2);

    // *** Get the points for the ellipse ***
    double sin_alpha;
    double cos_alpha;
    int x;
    int y;
    List<Point> points = new List<Point>();
    for (double alpha = 0; alpha < PI2; alpha += increment)
    {
        sin_alpha = Math.Sin(alpha);
        cos_alpha = Math.Cos(alpha);

        x = (int)(center_x + ((semi_major * cos_alpha * cos_beta) - (semi_minor * sin_alpha * sin_beta)));
        y = (int)(center_y + ((semi_major * cos_alpha * sin_beta) + (semi_minor * sin_alpha * cos_beta)));

        points.Add(new Point(x, y));
    }

    // *** Get point array ***
    Point[] point_array = points.ToArray();

    // *** Fill the ellipse ***
    g.FillPolygon(mybrush, point_array);

    // *** Draw the ellipse's border ***
    g.DrawPolygon(mypen, point_array);
}

private void FillCylinder(Graphics g, double center_x, double center_y, double height, double semi_minor, double semi_major, double angle)
{
    // *** Pens and brushes ***
    Pen mypen = new Pen(Color.Black);
    SolidBrush mybrush = new SolidBrush(Color.LightGray);

    // *** Semi height of the cylinder (to calculate center y position for ellipses) ***
    double semi_height = height / 2;

    // *** Rotation angle in radians, sine and cosine ***
    double beta = -angle * (Math.PI / 180);
    double sin_beta = Math.Sin(beta);
    double cos_beta = Math.Cos(beta);

    // *** Get the outer (leftmost and rightmost) points for the two ellipses ***
    double sin_alpha = Math.Sin(Math.PI);
    double cos_alpha = Math.Cos(Math.PI);

    int left_x1 = (int)(center_x + ((semi_major * cos_alpha * cos_beta) - (semi_minor * sin_alpha * sin_beta)));
    int left_y1 = (int)(center_y - semi_height + ((semi_major * cos_alpha * sin_beta) + (semi_minor * sin_alpha * cos_beta)));

    int left_x2 = (int)(center_x + ((semi_major * cos_alpha * cos_beta) - (semi_minor * sin_alpha * sin_beta)));
    int left_y2 = (int)(center_y + semi_height + ((semi_major * cos_alpha * sin_beta) + (semi_minor * sin_alpha * cos_beta)));

    sin_alpha = Math.Sin(0);
    cos_alpha = Math.Cos(0);

    int right_x1 = (int)(center_x + ((semi_major * cos_alpha * cos_beta) - (semi_minor * sin_alpha * sin_beta)));
    int right_y1 = (int)(center_y - semi_height + ((semi_major * cos_alpha * sin_beta) + (semi_minor * sin_alpha * cos_beta)));

    int right_x2 = (int)(center_x + ((semi_major * cos_alpha * cos_beta) - (semi_minor * sin_alpha * sin_beta)));
    int right_y2 = (int)(center_y + semi_height + ((semi_major * cos_alpha * sin_beta) + (semi_minor * sin_alpha * cos_beta)));

    // *** Draw the lower ellipse ***
    FillEllipse(g, Color.Black, Color.LightGray, center_x, center_y + semi_height, semi_minor, semi_major, angle);

    // *** Fill the central rectangle ***
    Point p_left_1 = new Point(left_x1, left_y1);
    Point p_right_1 = new Point(right_x1, right_y1);
    Point p_left_2 = new Point(left_x2, left_y2);
    Point p_right_2 = new Point(right_x2, right_y2);
    Point[] mypoints = new Point[] { p_left_1, p_right_1, p_right_2, p_left_2 };
    g.FillPolygon(mybrush, mypoints);

    // *** Draw the upper ellipse ***
    FillEllipse(g, Color.Black, Color.LightGray, center_x, center_y - semi_height, semi_minor, semi_major, angle);

    // *** Connect the outer points ***
    g.DrawLine(mypen, left_x1, left_y1, left_x2, left_y2);
    g.DrawLine(mypen, right_x1, right_y1, right_x2, right_y2);
}

private void picCanvas_Paint(object sender, PaintEventArgs e)
{
    FillCylinder(e.Graphics, picCanvas.Size.Width / 2, picCanvas.Size.Height / 2, picCanvas.Size.Height / 2, picCanvas.Size.Height / 8, picCanvas.Size.Width / 4, 10);
}


See the result here[^].

Of course you can also choose to continute with the "brute force" approach I showed earlier for getting the outer points, which is ok for any rotation angle. In that case I suggest you calculate the points for both ellipses and store them in point arrays, so that you can also get the outer points. Then, you can proceed to drawing:

C#
private class EllipseOuterXPoints
{
    internal int left_x = int.MaxValue;
    internal int left_y = int.MaxValue;
    internal int right_x = int.MinValue;
    internal int right_y = int.MinValue;

    internal void CheckPoint(int x, int y)
    {
        if (x < left_x)
        {
            left_x = x;
            left_y = y;
        }

        if (x > right_x)
        {
            right_x = x;
            right_y = y;
        }
    }
}

private Point[] GetEllipsePoints(double center_x, double center_y, double semi_minor, double semi_major, double angle, EllipseOuterXPoints OuterPoints)
{
    // *** Constants ***
    double PI2 = Math.PI * 2;

    // *** Major axis length ***
    double major = semi_major * 2;

    // *** Calculate increment by a rough estimation of the number of points needed (empirical!) ***
    double increment = (Math.PI * 2) / major;

    // *** Point array ***
    Point[] points = new Point[(int)major];

    // *** Rotation angle in radians, sine and cosine ***
    double beta = -angle * (Math.PI / 180);
    double sin_beta = Math.Sin(beta);
    double cos_beta = Math.Cos(beta);

    // *** Get the points for the ellipse ***
    double sin_alpha;
    double cos_alpha;
    int x;
    int y;
    int i = 0;
    for (double alpha = 0; alpha < PI2; alpha += increment)
    {
        sin_alpha = Math.Sin(alpha);
        cos_alpha = Math.Cos(alpha);

        x = (int)(center_x + ((semi_major * cos_alpha * cos_beta) - (semi_minor * sin_alpha * sin_beta)));
        y = (int)(center_y + ((semi_major * cos_alpha * sin_beta) + (semi_minor * sin_alpha * cos_beta)));

        points[i++] = new Point(x, y);

        // *** Get the outer points ***
        OuterPoints.CheckPoint(x, y);
    }

    // *** Return the point array ***
    return points;
}

private void FillCylinder_BruteForce(Graphics g, double center_x, double center_y, double height, double semi_minor, double semi_major, double angle)
{
    // *** Pens and brushes ***
    Pen mypen = new Pen(Color.Black);
    SolidBrush mybrush = new SolidBrush(Color.LightGray);

    // *** Semi height of the cylinder (to calculate center y position for ellipses) ***
    double semi_height = height / 2;

    // *** Get the points for the ellipses ***
    EllipseOuterXPoints OuterPoints1 = new EllipseOuterXPoints();
    EllipseOuterXPoints OuterPoints2 = new EllipseOuterXPoints();
    Point[] points1 = GetEllipsePoints(center_x, center_y - semi_height, semi_minor, semi_major, angle, OuterPoints1);
    Point[] points2 = GetEllipsePoints(center_x, center_y + semi_height, semi_minor, semi_major, angle, OuterPoints2);

    // *** Draw the lower ellipse ***
    g.FillPolygon(mybrush, points2);
    g.DrawPolygon(mypen, points2);

    // *** Fill the central rectangle ***
    Point p_left_1 = new Point(OuterPoints1.left_x, OuterPoints1.left_y);
    Point p_right_1 = new Point(OuterPoints1.right_x, OuterPoints1.right_y);
    Point p_left_2 = new Point(OuterPoints2.left_x, OuterPoints2.left_y);
    Point p_right_2 = new Point(OuterPoints2.right_x, OuterPoints2.right_y);
    Point[] mypoints = new Point[] { p_left_1, p_right_1, p_right_2, p_left_2 };
    g.FillPolygon(mybrush, mypoints);

    // *** Draw the upper ellipse ***
    g.FillPolygon(mybrush, points1);
    g.DrawPolygon(mypen, points1);

    // *** Connect the outer points ***
    g.DrawLine(mypen, OuterPoints1.left_x, OuterPoints1.left_y, OuterPoints2.left_x, OuterPoints2.left_y);
    g.DrawLine(mypen, OuterPoints1.right_x, OuterPoints1.right_y, OuterPoints2.right_x, OuterPoints2.right_y);
}

private void picCanvas_Paint(object sender, PaintEventArgs e)
{
    FillCylinder_BruteForce(e.Graphics, picCanvas.Size.Width / 2, picCanvas.Size.Height / 2, picCanvas.Size.Height / 2, picCanvas.Size.Height / 8, picCanvas.Size.Width / 4, 45);
}


See the result here[^].

Well, this should give you enough meat to chew I hope. Enjoy! Smile | :)
2+2=5 for very large amounts of 2
(always loved that one hehe!)

GeneralRe: Filling a cylinder or a tube Pin
Valeriant6-Apr-10 2:21
Valeriant6-Apr-10 2:21 
GeneralRe: Filling a cylinder or a tube Pin
Moreno Airoldi6-Apr-10 4:11
Moreno Airoldi6-Apr-10 4:11 
GeneralRe: Filling a cylinder or a tube Pin
Andy_L_J25-Mar-10 19:50
Andy_L_J25-Mar-10 19:50 
GeneralRe: Filling a cylinder or a tube Pin
Moreno Airoldi25-Mar-10 22:27
Moreno Airoldi25-Mar-10 22:27 
QuestionFirewall Bypass via Compression Encoding Pin
Khalib Ismail19-Mar-10 16:05
Khalib Ismail19-Mar-10 16:05 
AnswerRe: Firewall Bypass via Compression Encoding Pin
Michel Godfroid1-Apr-10 6:12
Michel Godfroid1-Apr-10 6:12 
Question2D collision detection between a square and rectangle [modified] Pin
venomation8-Mar-10 13:10
venomation8-Mar-10 13:10 
AnswerRe: 2D collision detection between a square and rectangle Pin
Luc Pattyn8-Mar-10 13:42
sitebuilderLuc Pattyn8-Mar-10 13:42 
GeneralRe: 2D collision detection between a square and rectangle Pin
venomation8-Mar-10 13:53
venomation8-Mar-10 13:53 
GeneralRe: 2D collision detection between a square and rectangle Pin
venomation8-Mar-10 14:49
venomation8-Mar-10 14:49 
QuestionDesigning Parallel Algorithms Pin
ProtoBytes2-Mar-10 7:43
ProtoBytes2-Mar-10 7:43 
AnswerRe: Designing Parallel Algorithms Pin
Chris Losinger5-Mar-10 8:51
professionalChris Losinger5-Mar-10 8:51 
AnswerRe: Designing Parallel Algorithms [Modified - Spell Checked] [modified] Pin
ProtoBytes5-Mar-10 11:57
ProtoBytes5-Mar-10 11:57 
GeneralRe: Designing Parallel Algorithms [Modified - Spell Checked] Pin
Chris Losinger8-Mar-10 4:27
professionalChris Losinger8-Mar-10 4:27 
AnswerRe: Designing Parallel Algorithms Pin
Fatbuddha 119-Mar-10 2:24
Fatbuddha 119-Mar-10 2:24 
QuestionClosest Polygon Pin
Richard Andrew x6418-Feb-10 17:36
professionalRichard Andrew x6418-Feb-10 17:36 
AnswerRe: Closest Polygon Pin
Som Shekhar18-Feb-10 19:00
Som Shekhar18-Feb-10 19:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.