I am using Cairo Graphics along with RichClient6 (which is a wrapper), but I believe this fact is not so important.
I need to get the extents of a path. This works fine, but not when the matrix is rotated. I do not understand what happens in this case, and I have not been able to solve it myself yet.
I would like to ask if anybody see what I need to do differently in order to get the extents reliably even when the matrix is rotated.
Thank you.
Here are some outputs that show how the extents change:
Angle: 1, Path Extents: -2,8 -6 343,8 169
Angle: 2, Path Extents: -5,7 -11,9 346,7 174,9
Angle: 3, Path Extents: -8,5 -17,8 349,5 180,8
Angle: 4, Path Extents: -11,3 -23,7 352,3 186,7
Angle: 5, Path Extents: -14,2 -29,6 355,2 192,6
Angle: 6, Path Extents: -16,9 -35,4 357,9 198,4
Angle: 7, Path Extents: -19,7 -41,2 360,7 204,2
Angle: 8, Path Extents: -22,5 -47 363,5 210
Angle: 9, Path Extents: -25,2 -52,7 366,2 215,7
Angle: 10, Path Extents: -27,9 -58,3 368,9 221,3
Angle: 11, Path Extents: -30,5 -63,9 371,5 226,9
Angle: 12, Path Extents: -33,2 -69,4 374,1 232,3
Angle: 13, Path Extents: -35,7 -74,7 376,7 237,7
Angle: 14, Path Extents: -38,3 -80 379,3 243
Angle: 15, Path Extents: -40,7 -85,2 381,7 248,3
Angle: 16, Path Extents: -43,2 -90,4 384,2 253,4
Angle: 17, Path Extents: -45,6 -95,3 386,6 258,3
Angle: 18, Path Extents: -47,9 -100,2 388,9 263,2
Angle: 19, Path Extents: -50,2 -105 391,2 268
Angle: 20, Path Extents: -52,4 -109,6 393,4 272,6
Angle: 21, Path Extents: -54,5 -114,1 395,5 277,1
Angle: 22, Path Extents: -56,6 -118,4 397,6 281,4
Angle: 23, Path Extents: -58,6 -122,6 399,6 285,6
Angle: 24, Path Extents: -60,6 -126,7 401,6 289,7
Angle: 25, Path Extents: -62,4 -130,6 403,4 293,6
Angle: 26, Path Extents: -64,2 -134,4 405,2 297,4
Angle: 27, Path Extents: -65,9 -137,9 406,9 300,9
Angle: 28, Path Extents: -67,6 -141,4 408,6 304,4
Angle: 29, Path Extents: -69,1 -144,6 410,1 307,6
Angle: 30, Path Extents: -70,6 -147,7 411,6 310,7
Angle: 31, Path Extents: -72 -150,5 413 313,5
Angle: 32, Path Extents: -73,3 -153,2 414,3 316,2
Angle: 33, Path Extents: -74,5 -155,8 415,5 318,8
Angle: 34, Path Extents: -75,6 -158,1 416,6 321,1
Angle: 35, Path Extents: -76,6 -160,2 417,6 323,2
Angle: 36, Path Extents: -77,5 -162,2 418,5 325,2
Angle: 37, Path Extents: -78,3 -163,9 419,3 326,9
Angle: 38, Path Extents: -79,1 -165,4 420,1 328,4
Angle: 39, Path Extents: -79,7 -166,8 420,7 329,8
Angle: 40, Path Extents: -80,3 -167,9 421,3 330,9
Angle: 41, Path Extents: -80,7 -168,8 421,7 331,8
Angle: 42, Path Extents: -81,1 -169,6 422,1 332,6
Angle: 43, Path Extents: -81,3 -170,1 422,3 333,1
Angle: 44, Path Extents: -81,5 -170,4 422,5 333,4
Angle: 45, Path Extents: -81,5 -170,5 422,5 333,5
Angle: 46, Path Extents: -81,5 -170,4 422,5 333,4
Angle: 47, Path Extents: -81,3 -170,1 422,3 333,1
Angle: 48, Path Extents: -81,1 -169,6 422,1 332,6
Angle: 49, Path Extents: -80,7 -168,8 421,7 331,8
Angle: 50, Path Extents: -80,3 -167,9 421,3 330,9
Angle: 51, Path Extents: -79,7 -166,8 420,7 329,8
Angle: 52, Path Extents: -79,1 -165,4 420,1 328,4
Angle: 53, Path Extents: -78,3 -163,9 419,3 326,9
Angle: 54, Path Extents: -77,5 -162,2 418,5 325,2
Angle: 55, Path Extents: -76,6 -160,2 417,6 323,2
And this is the code:
Public Sub DrawTo(ByRef uDestCC As cCairoContext, ByVal uLeft As Long, ByVal uTop As Long)
Dim dblOffx As Double: Dim dblOffy As Double
' Calculate offsets based on alignment and scaling
dblOffx = Me.AlignmentFactorX * ((m_Img.width * Me.ScaleFactorW) / 2)
dblOffy = Me.AlignmentFactorY * ((m_Img.height * Me.ScaleFactorH) / 2)
Dim dblNewX1 As Double : Dim dblNewY1 As Double
dblNewX1 = (uLeft + dblOffx)
dblNewY1 = (uTop + dblOffy)
Dim dblNewX2 As Double : Dim dblNewY2 As Double
dblNewX2 = -(m_Img.width / 2) - (Me.CenterOffsetX / 2)
dblNewY2 = -(m_Img.height / 2) - (Me.CenterOffsetY / 2)
m_Matrix.TranslateCoords dblNewX1, dblNewY1
m_Matrix.RotateCoordsDeg m_sngAngleDeg
m_Matrix.ScaleCoords Me.ScaleFactorW, Me.ScaleFactorH
m_Matrix.TranslateCoords dblNewX2, dblNewY2
' Set the final transformation
Set uDestCC.Matrix = m_Matrix
' Now draw the image with the same transformations
uDestCC.RenderSurfaceContent m_Img, 0, 0
' Define a rectangle path representing the image area after rotation is set
uDestCC.Rectangle 0, 0, m_Img.width, m_Img.height
' Get the extents now, with rotation already applied
uDestCC.GetPathExtents m_dblTopX, m_dblTopY, m_dblBottomRightX, m_dblBottomRightY
' Clear the path
uDestCC.ClearPath False
m_Matrix.ResetToIdentity
Debug.Print "Angle: " & m_sngAngleDeg & ", Path Extents:", Round(m_dblTopX, 1), Round(m_dblTopY, 1), Round(m_dblBottomRightX, 1), Round(m_dblBottomRightY, 1)
End Sub
Somebody suggest using CopyPath.
In the wrapper I found this:
Function CopyPath([AsFlatPath As Boolean], [FlatPrecision As Double = 0,1]) As cCairoPath
Member of RC6.cCairoContext
The class cCairoPath offers the following:
Function CalculateDistances(Distances() As Double) As Double
Property EntriesCount As Long
Function GetPathEntry(IndexZeroBased As Long, EntryType As cairo_path_data_type_enm, [X0 As Double], [Y0 As Double], [X1 As Double], [Y1 As Double], [X2 As Double], [Y2 As Double])
Sub ProjectPathData_Using(FlattenedBasePath As cCairoPath, [ScaleX As Double], [ScaleY As Double])
Sub ProjectPathData_Using(FlattenedBasePath As cCairoPath, [ScaleX As Double], [ScaleY As Double])
I do not speak whatever language this is, so I am just guessing.
I need to get the extents of a path. This works fine, but not when the matrix is rotated. I do not understand what happens in this case, and I have not been able to solve it myself yet.
From this description, I guess you are running into a limit of cairo. Internally, cairo always works in surface coordinates (i.e. any rotation from e.g. cairo_rotate()
gets immediately applied). Only across the outside API does it apply the rotation.
Thus, if you add a circle with center 0, 0 and radius 10 to the current path, cairo internally records that the extents of the current path go from -10, -10 to 10, 10. So at this step, a rectangle is put around the circle. If you now ask for the extents of the path, you get -10, -10 to 10, 10.
Let us repeat this with a rotation of 45°. Cairo applies this rotation immediately when constructing the path, but in this case it does not matter, since a circle at 0, 0 looks the same before and after rotation. However, internally cairo still records the extents as going from -10, -10 to 10, 10 in surface coordinates. If you now ask cairo for the extents, it goes something like this: I do not know the tight extents, but I know that everything is within a rectangle of -10, -10 to 10, 10. However, you want a 45° rotation on this. So I will rotate this rectangle. In user space, the extents of this will be something like -14.14, -14.14 to 14.14.
So the short version: Cairo tracks the extents in surface coordinates. The user coordinate translation is only computed when you ask for this and at this step a worse-case analysis of "a rectangle is drawn" is made. Thus, you get larger extents.
I would like to ask if anybody see what I need to do differently in order to get the extents reliably even when the matrix is rotated.
Quick, spontaneous and untested idea: Use something like cairo_copy_path_flat()
to query the current path. I think the coordinates you get will be in user space. Thus, you can compute its extents yourself with a min
and max
over all the coordinates.