CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 27
  1. #1
    Join Date
    Feb 2001
    Posts
    2,455

    Moving a series of points to be centered on a given point

    I have the 5 points of a star calculated as follows:
    Code:
    	// Calculate the outer points of the star
    	for(int i = 0; i < m_nPoints; i++)
    	{
    		m_dAngle += m_dTheta;
    		int X = (int)(m_dRadius * cos(m_dAngle));
    		int Y = (int)(m_dRadius * sin(m_dAngle));
    	
    		m_ptsOuter[i].x = X;
    		m_ptsOuter[i].y = Y;
    	}
    Now I want this star to be centered at a point given by m_ptCenter.
    How can I move the points defined in m_ptsOuter to be centered on m_ptCenter?

    Mike B

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,430

    Re: Moving a series of points to be centered on a given point

    Code:
     	for(int i = 0; i < m_nPoints; i++)
    	{
    		m_ptsOuter[i] += m_ptCenter;
    	}

  3. #3
    Join Date
    Jun 2003
    Location
    Armenia, Yerevan
    Posts
    720

    Re: Moving a series of points to be centered on a given point

    You need to determine the current center, then update all x,y pairs by delta values of new and old centers:

    dx = new_center.x - old_center.x;
    dy = new_center.y - old_center.y;
    for each point in points do
    point.x = point.x + dx;
    point.y = point.y + dy;

  4. #4
    Join Date
    Feb 2001
    Posts
    2,455

    Re: Moving a series of points to be centered on a given point

    Quote Originally Posted by AvDav
    You need to determine the current center, then update all x,y pairs by delta values of new and old centers:

    dx = new_center.x - old_center.x;
    dy = new_center.y - old_center.y;
    for each point in points do
    point.x = point.x + dx;
    point.y = point.y + dy;
    Hmmm, well, I should have known this actually. Anyway, I used this method, but the polygon (not drawing star yet) isn't centering on the point.

    I have attached an application that draws this polygon in a dialog.

    In the dialogs OnPaint() I get the center of the dialog, set the radius of the star, set the center point, call InitStar() and then draw it. It isn't centering on the dialog.

    Any ideas?

    Mike Bujak
    Attached Files Attached Files

  5. #5
    Join Date
    Sep 2002
    Location
    14° 39'19.65"N / 121° 1'44.34"E
    Posts
    9,815

    Re: Moving a series of points to be centered on a given point

    Quote Originally Posted by MikeB
    In the dialogs OnPaint() I get the center of the dialog, set the radius of the star, set the center point, call InitStar() and then draw it. It isn't centering on the dialog.
    The flaw is in your CStar::GetContainingRect() method:
    Code:
    CRect CStar::GetContainingRect()
    {
      CPoint ptCur = m_ptsOuter[0];
      CRect rc (ptCur.x,ptCur.y,ptCur.x,ptCur.y);
    
      for(int i = 1; i < m_nPoints; i++)
      {
        CPoint ptTemp = m_ptsOuter[i];
        if(ptTemp.x < rc.left)
          c.left = ptTemp.x;
        else   if(ptTemp.x > rc.right)
          rc.right = ptTemp.x;
        else   if(ptTemp.y < rc.top)
          rc.top = ptTemp.y;
        else   if(ptTemp.y > rc.bottom)
          rc.bottom = ptTemp.y;
      }
    
      return rc;
    }
    Problem is that you are using else-if for those four conditions - however, they are not mutually exclusive: For example, when ptTemp.x happens to be < rc.left, the y coordinates won't be tested any more, resulting in wrong values of your resulting rectangle - and since you are using it for determining the drawing center later on, your shape gets offset.

    Besides that: I wonder why you need that step (calculating the containing rect, and then getting its center point) at all? The way you currently create your polygon, the center point is always (0,0) - and if you fix GetContainingRect(), you will see that the center point you get back is always (obviously) (0,0).

  6. #6
    Join Date
    Feb 2001
    Posts
    2,455

    Smile Re: Moving a series of points to be centered on a given point

    Quote Originally Posted by gstercken
    The flaw is in your CStar::GetContainingRect() method:
    Code:
    CRect CStar::GetContainingRect()
    {
      CPoint ptCur = m_ptsOuter[0];
      CRect rc (ptCur.x,ptCur.y,ptCur.x,ptCur.y);
    
      for(int i = 1; i < m_nPoints; i++)
      {
        CPoint ptTemp = m_ptsOuter[i];
        if(ptTemp.x < rc.left)
          c.left = ptTemp.x;
        else   if(ptTemp.x > rc.right)
          rc.right = ptTemp.x;
        else   if(ptTemp.y < rc.top)
          rc.top = ptTemp.y;
        else   if(ptTemp.y > rc.bottom)
          rc.bottom = ptTemp.y;
      }
    
      return rc;
    }
    Problem is that you are using else-if for those four conditions - however, they are not mutually exclusive: For example, when ptTemp.x happens to be < rc.left, the y coordinates won't be tested any more, resulting in wrong values of your resulting rectangle - and since you are using it for determining the drawing center later on, your shape gets offset.

    Besides that: I wonder why you need that step (calculating the containing rect, and then getting its center point) at all? The way you currently create your polygon, the center point is always (0,0) - and if you fix GetContainingRect(), you will see that the center point you get back is always (obviously) (0,0).
    You are absolutely correct, but I want to ensure that if I ever use this class for anything other then my current project, that a star can in fact be moved from its current position. I know I create the orginal polygon at 0,0, but lets say I move it, then move it again?

    Actually come to think of it, you are right, I should not need this step at all. If the user was to move it, all I would have to do is re-create the polygon and reposition its center.

    Good point. 5 Stars for you!

    Mike B

  7. #7
    Join Date
    Sep 2002
    Location
    14° 39'19.65"N / 121° 1'44.34"E
    Posts
    9,815

    Re: Moving a series of points to be centered on a given point

    Quote Originally Posted by MikeB
    Good point. 5 Stars for you!
    Thanks - correctly centered ones, I hope?

  8. #8
    Join Date
    Feb 2001
    Posts
    2,455

    Re: Moving a series of points to be centered on a given point

    Now I am trying to draw the star by the points defining the perimeter of the star shape. To do this, I create 2 polygons, one for the inside points of the star and one for the outside of the star. EG, for a 5 point star, there are a total of 10 points along the perimeter.

    I am getting all the points correctly, but when I try to combine the points into one array and call the CDC::Polygon(...) function, the star shape is not correct.. All the points are, but the shape seems inverted or something.

    See attached program for all the code:

    here is my InitStar() and DrawStar(...) functions for those that do not
    want to download project:
    Code:
    void CStar::InitStar()
    {
    	m_dTheta = (PI*2)/m_nPoints;	// Angle to each point, outer circle
    
    	if(m_ptsOuter)
    		delete [] m_ptsOuter;
    	
    	m_ptsOuter = new CPoint[m_nPoints];
    	
    	if(m_ptsInner)
    		delete [] m_ptsInner;
    
    	m_ptsInner = new CPoint[m_nPoints];
    
    	// Calculate the outer points of the star
    	for(int i = 0; i < m_nPoints; i++)
    	{
    		m_dAngle += m_dTheta;
    		int X = (int)(m_dRadius * cos(m_dAngle));
    		int Y = (int)(m_dRadius * sin(m_dAngle));
    	
    		m_ptsOuter[i].x = X;
    		m_ptsOuter[i].y = Y;
    	}
    
    	// Calculate the inner points of the star
    	double dRad = m_dRadius / 2;
    	double dAngle = m_dAngle + (m_dTheta / 2);
    
    	for(i = 0; i < m_nPoints; i++)
    	{
    		int X = (int)(dRad * cos(dAngle));
    		int Y = (int)(dRad * sin(dAngle));
    	
    		m_ptsInner[i].x = X;
    		m_ptsInner[i].y = Y;
    
    		dAngle += m_dTheta;
    	}
    
    	// Center star points
    	for(i = 0; i < m_nPoints; i++)
    	{
    		m_ptsOuter[i].x += m_ptCenter.x;
    		m_ptsOuter[i].y += m_ptCenter.y;
    		
    		m_ptsInner[i].x += m_ptCenter.x;
    		m_ptsInner[i].y += m_ptCenter.y;
    	}
    }
    
    void CStar::DrawStar(CDC* pDC)
    {
    	CPoint* pts = new CPoint[m_nPoints*2];
    	int nPoint = 0;
    	for(int i = 0; i < m_nPoints * 2; i++)
    	{
    		if(i % 2 == 0)
    		{
    			pts[i] = m_ptsOuter[nPoint];
    		}
    		else
    		{
    			pts[i] = m_ptsInner[nPoint];
    			++nPoint;
    		}
    	}
    	
    	for(i = 0; i < m_nPoints * 2; i++)
    	{
    		CPoint pt = pts[i];
    	}
    
    	pDC->Polygon(pts, m_nPoints * 2);
    	delete [] pts;
    }
    Thanks

    Mike B
    Attached Files Attached Files

  9. #9
    Join Date
    Feb 2001
    Posts
    2,455

    Re: Moving a series of points to be centered on a given point

    Update:

    I find if I reverse the for loop in the DrawStar(...) function, it is almost correct, but the top of the star goes bad somehow.

    Code:
    void CStar::DrawStar(CDC* pDC)
    {
    	CPoint* pts = new CPoint[m_nPoints*2];
    	int nPoint = 4;
    	for(int i = m_nPoints * 2 - 1; i >= 0; --i)
    	{
    		if(i % 2 == 0)
    		{
    			pts[i] = m_ptsOuter[nPoint];
    		}
    		else
    		{
    			pts[i] = m_ptsInner[nPoint];
    			--nPoint;
    		}
    	}
    	
    	pDC->Polygon(pts, m_nPoints * 2);
    	delete [] pts;
    }

  10. #10
    Join Date
    Sep 2002
    Location
    14° 39'19.65"N / 121° 1'44.34"E
    Posts
    9,815

    Re: Moving a series of points to be centered on a given point

    Quote Originally Posted by MikeB
    I find if I reverse the for loop in the DrawStar(...) function, it is almost correct, but the top of the star goes bad somehow.
    Looks like trial-and-error, if you ask me...

    Again, your code is unnecessarily complicated (and hence error-prone). Why these two separate arrays for inner and outer points, the two separate loops, and later merging both arrays into one? It would be far easier to have one single array of (m_nPoints * 2) elements, and loop from 0 to < (m_nPoints * 2) - the only thing you need to do is to use the inner and outer radius in an alternating way for calculating the point, depending on the value of i % 2, and incrementing the angle by (m_dTheta / 2). This automatically gets you the polygon points in the right order, without having to deal with three arrays.

  11. #11
    Join Date
    Feb 2001
    Posts
    2,455

    Re: Moving a series of points to be centered on a given point

    Quote Originally Posted by gstercken
    Looks like trial-and-error, if you ask me...

    Again, your code is unnecessarily complicated (and hence error-prone). Why these two separate arrays for inner and outer points, the two separate loops, and later merging both arrays into one? It would be far easier to have one single array of (m_nPoints * 2) elements, and loop from 0 to < (m_nPoints * 2) - the only thing you need to do is to use the inner and outer radius in an alternating way for calculating the point, depending on the value of i % 2, and incrementing the angle by (m_dTheta / 2). This automatically gets you the polygon points in the right order, without having to deal with three arrays.
    LOL, easy enough, you are the man. 5 More stars for you, correctly centered and drawn!!!



    Code:
    void CStar::InitStar()
    {
    	m_dTheta = (PI*2)/m_nPoints;	// Angle to each point, outer circle
    
    	if(m_ptsOuter)
    		delete [] m_ptsOuter;
    	
    	m_ptsOuter = new CPoint[m_nPoints*2];
    	
    	// Calculate the outer points of the star
    	for(int i = 0; i < m_nPoints * 2; i++)
    	{
    		double dRad = i%2==0 ? m_dRadius : m_dRadius/2;
    
    		int X = (int)(dRad * cos(m_dAngle));
    		int Y = (int)(dRad * sin(m_dAngle));
    		
    		m_ptsOuter[i].x = X;
    		m_ptsOuter[i].y = Y;
    		m_dAngle += m_dTheta/2;
    	}
    
    	// Center star points
    	for(i = 0; i < m_nPoints*2; i++)
    	{
    		m_ptsOuter[i].x += m_ptCenter.x;
    		m_ptsOuter[i].y += m_ptCenter.y;
    	}
    }
    
    void CStar::DrawStar(CDC* pDC)
    {
    	pDC->Polygon(m_ptsOuter, m_nPoints * 2);
    }
    Mike B

  12. #12
    Join Date
    Sep 2002
    Location
    14° 39'19.65"N / 121° 1'44.34"E
    Posts
    9,815

    Re: Moving a series of points to be centered on a given point

    Quote Originally Posted by MikeB
    5 More stars for you, correctly centered and drawn!!!
    Thanks...

    Btw, one more suggestion for further optimizing (and simplifying) your code: Instead of deleting and reallocating your point array each time you draw the shape, you could move this to the ctor (where the number of points is already known). The only other place where you would then need to delete and reallocate the array is in your setter for the number of points (SetPoints()).

  13. #13
    Join Date
    Feb 2001
    Posts
    2,455

    Re: Moving a series of points to be centered on a given point

    Here is the working app so far. I am only posting this in the case
    that someone else is interested ever in doing the same type of thing.

    The purpose of this "star" class is to be able to display customer ratings
    based on a 5 star systems. I know I could have just displayed this numerically but my application is already lacking "fun" so I thought I would
    implement a graphical display of the star system.

    Anyway, now I need to come up with a way to paint these stars either in whole or partial. I know I can find the intersecting points of a of a dividing line, say at 25 percent to indicate a 1/4 star, and draw two polygons (the left and right) of the star, but does anyone have an easier method. As you can see by the previous posts, I am not one to take the easy route out.

    Any ideas?

    Mike B
    Attached Files Attached Files

  14. #14
    Join Date
    Feb 2001
    Posts
    2,455

    Re: Moving a series of points to be centered on a given point

    Quote Originally Posted by gstercken
    Thanks...

    Btw, one more suggestion for further optimizing (and simplifying) your code: Instead of deleting and reallocating your point array each time you draw the shape, you could move this to the ctor (where the number of points is already known). The only other place where you would then need to delete and reallocate the array is in your setter for the number of points (SetPoints()).
    I have moved the allocation to set points, which makes sense. But the points were not calculated each time it was drawn. Only when InitStar() was called which builds the star.

    Should I call InitStar from inside all my properties set functions? Or let it be that it is called at the time of creation?

    Mike B

  15. #15
    Join Date
    Sep 2002
    Location
    14° 39'19.65"N / 121° 1'44.34"E
    Posts
    9,815

    Re: Moving a series of points to be centered on a given point

    Quote Originally Posted by MikeB
    The purpose of this "star" class is to be able to display customer ratings
    based on a 5 star systems. I know I could have just displayed this numerically but my application is already lacking "fun" so I thought I would
    implement a graphical display of the star system.
    That's fine - but honestly, in a real-world app, I would do this with pre-drawn bitmaps for the stars... I assume that you need partially filled stars for displaying fractional ratings, right? And having only 4 differently filled star bitmaps (0%, 25%, 50% and 100%) already gives you 20 different levels with 5 stars - pretty much for any rating system.

    But for the heck of it: The geometrical approach you mentioned (finding the intersecting line and drawing two separate filled polygons seems indeed to be the easiest - especially since you're already bothered with the math to dynamically calculate the polygon points. Any other approach would either use offscreen DCs and clipping regions, or temporary offscreen bitmaps and blitting with ternary ROP codes to combine certain bits of say, the polygon bitmap and a rectangle that determines the fill state. While they involve less geometry math, I estimate that the boilerplate code you need to make them work would be more, in the end, than the approach you mentioned yourself. In any case: There is no simple GDI approach for filling a polygon only partially.

Page 1 of 2 12 LastLast

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