Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Draw polygon

Status
Not open for further replies.

BasicBoy

Programmer
Feb 22, 2008
156
ZA
I have difficulty drawing a polygon to the right scale.
I use the Polygon API.
However, my scales might be the problem. I have intervals of 1 to 25 as the X (horizontal axis) and Dollars from 300000 to 3000000 on the Y (vertical) axis.
Can I use the selfsame coordinates to draw the polygon or do I have to scale and offset them.
I know the API draws in pixels, but do not know how to handle that.
Presently I wish to draw a polygon with the following coordinates:
PolyPoint1.x=1
PolyPoint1.y=300000

PolyPoint2.x=1
PolyPoint2.y=800000

PolyPoint3.x=20
PolyPoint3.y=900000

PolyPoint4.x=20
PolyPoint4.y=500000

I have set the fillcolor and fillstyle to their proper values.

Thanks
 
>Can I use the selfsame coordinates to draw the polygon

No, you need to scale and offset. Unless, of course, you have redefined the scale and origins of your viewport. You might want to have a look at the following API calls: SetMapMode, SetWindowExtEx, SetViewportExtEx, and SetWindowOrgEx
 
Try building on something like this;
Code:
'On a new Form with a Command1
Private Type POINTAPI
        x As Long
        y As Long
End Type
Private Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long
Dim DataPoints(0 To 3) As POINTAPI
Dim PolyPoints(0 To 3) As POINTAPI

Private Sub Command1_Click()

    Dim xscale!, yscale!, xmax!, ymax!
 
    DataPoints(0).x = 1
    DataPoints(0).y = 800000
    DataPoints(1).x = 1
    DataPoints(1).y = 300000
    DataPoints(2).x = 20
    DataPoints(2).y = 500000    '900000
    DataPoints(3).x = 20
    DataPoints(3).y = 900000    '500000
    'original data (remmed) gives a crossed polygon

    'normalize and scale data to a 100*100 user coordinate grid with a border 10 wide all round
    Scale (-10, 110)-(110, -10)
    Line (0, 100)-(100, 0), vbGreen, B  'draw line round the plot rectangle
    
    xmax = 21: ymax = 1000000
    xscale = 100 / xmax: yscale = 100 / ymax
    
    For i = 0 To UBound(DataPoints)
        Scale (-10, 110)-(110, -10)
        CurrentX = DataPoints(i).x * xscale
        CurrentY = DataPoints(i).y * yscale
        Circle (CurrentX, CurrentY), 1, vbRed
        ScaleMode = vbPixels
        PolyPoints(i).x = CurrentX
        PolyPoints(i).y = CurrentY
    Next
    FillStyle = vbUpwardDiagonal: FillColor = vbBlue
    Polygon hdc, PolyPoints(0), 4

End Sub
 
Hugh,
Thanks for your contribution.
I have just found the solution on another website and it worked very well. I therefore will not test your solution.
The secret lies in converting the pixel coordinates to the user coordinates.

 
Perhaps you could provide the link that you used so that others finding this question can also see the answer.
 
>The secret lies in converting the pixel coordinates to the user coordinates.
>Here is the link ...

Ah, so pretty much HughLerwill's solution, then. And does indeed involve scaling ...

>The secret lies in converting the pixel coordinates to the user coordinates.

Actually, it's the other way around ...
 
Just for fun, here's my version:

Code:
[blue]Option Explicit

Private Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long
Private Type POINTAPI
        x As Long
        y As Long
End Type


Private Sub Command1_Click()
    Dim mypoly()  As POINTAPI
    Dim lp As Long
    
    Picture1.Scale (0, 300000)-(25, 3000000)
    
    ReDim mypoly(0 To 3) As POINTAPI
    
    mypoly(0).x = 1
    mypoly(0).y = 300000
    
    mypoly(1).x = 1
    mypoly(1).y = 800000
    
    mypoly(2).x = 20
    mypoly(2).y = 900000
    
    mypoly(3).x = 20
    mypoly(3).y = 500000
    
    [green]' OK, let's scale our user coordinates to correct pixel value[/green]
    For lp = LBound(mypoly) To UBound(mypoly)
        mypoly(lp).x = Picture1.ScaleX(mypoly(lp).x - Picture1.ScaleLeft, Picture1.ScaleMode, vbPixels)
        mypoly(lp).y = Picture1.ScaleY(mypoly(lp).y - Picture1.ScaleTop, Picture1.ScaleMode, vbPixels)
    Next
    
    Polygon Picture1.hdc, mypoly(0), 4
End Sub[/blue]
 
That is scary similar to the code I have been using for year. I have a couple differences in my code, but they exist for micro-optimization reasons.

I use a with block inside the scaling loop because you are accessing the array 4 times and it is faster to use a with block. I also set variables for the picture box scale left, scale top, and scale mode before the loop. Again, because it is faster to access a local variable than it is to access a property.

In my case, I could be displaying dozens of polygons, each with hundreds of points, so the little bits of time add up to something real.

Regardless, in my experience, this is the fastest and cleanest way to draw polygons.


-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
>so the little bits of time add up to something real

They certainly can. But (as I know you are aware) this was just an example, not optimised, production code.
 
Strongm, I only mention it because it is the next logical step once your code is thoroughly understood and implemented.



-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top