Simple way to rotate region (Views: 2141)
Problem/Question/Abstract: Simple function returning rotated region. Pprocedure doing the same with source region. Answer: It's the simple function returning new region rotated to the angle that you want around the source region. Source region doesn't change. The second procedure does the same with source region without creating new region. I hope this will be useful. Comments are provided along the code function _RotateRgn(ARgn: HRGN; ADegree: Real): HRGN; var wXFORM: XFORM; // transformation structure, see Windows API kRgnD: DWord; // count of RGNDATA structures in region RgnData: PRgnData; // pointer to region data Rt: TRect; kX, kY: Integer; begin if (ARgn = 0) or (ADegree = 0) then Exit; // Get region's surrounding rectangular GetRgnBox(ARgn, Rt); // Move source region so that the centre of its surrounding rectangular // goes to the left top corner of a window kX := Rt.Left + (Rt.Right - Rt.Left) div 2; kY := Rt.Top + (Rt.Bottom - Rt.Top) div 2; OffsetRgn(ARgn, -kX, -kY); // Fill XFORM according to task (rotate region) FillChar(wXFORM, SizeOf(wXFORM), #0); wXFORM.eM11 := Cos(ADegree / 180 * pi); wXFORM.eM12 := -Sin(ADegree / 180 * pi); wXFORM.eM21 := -wXFORM.eM12; wXFORM.eM22 := wXFORM.eM11; // Prepare buffer to store region data kRgnD := GetRegionData(ARgn, 0, nil); GetMem(RgnData, SizeOf(RGNDATA) * kRgnD); // ..and fill the buffer with region's data GetRegionData(ARgn, kRgnD, RgnData); // ..move source region to its initial position OffsetRgn(ARgn, kX, kY); // Create output region using data in the buffer and transformation wXFORM Result := ExtCreateRegion(@wXFORM, kRgnD, RgnData^); // Move output region on a place of source region OffsetRgn(Result, kX, kY); FreeMem(RgnData); end; procedure _RotateRgnEx(var ARgn: HRGN; ADegree: Real); var wXFORM: XFORM; // transformation structure, see Windows API kRgnD: DWord; // count of RGNDATA structures in region RgnData: PRgnData; // pointer to region data Rt: TRect; kX, kY: Integer; begin if (ARgn = 0) or (ADegree = 0) then Exit; // Get region's surrounding rectangular GetRgnBox(ARgn, Rt); // Move source region so that the centre of its surrounding rectangular // goes to the left top corner of a window kX := Rt.Left + (Rt.Right - Rt.Left) div 2; kY := Rt.Top + (Rt.Bottom - Rt.Top) div 2; OffsetRgn(ARgn, -kX, -kY); // Fill XFORM according to task (rotate region) FillChar(wXFORM, SizeOf(wXFORM), #0); wXFORM.eM11 := Cos(ADegree / 180 * pi); wXFORM.eM12 := -Sin(ADegree / 180 * pi); wXFORM.eM21 := -wXFORM.eM12; wXFORM.eM22 := wXFORM.eM11; // Prepare buffer to store region data kRgnD := GetRegionData(ARgn, 0, nil); GetMem(RgnData, SizeOf(RGNDATA) * kRgnD); // ..and fill the buffer with region's data GetRegionData(ARgn, kRgnD, RgnData); // ..delete source region DeleteObject(ARgn); // Create new region using data in the buffer and transformation wXFORM ARgn := ExtCreateRegion(@wXFORM, kRgnD, RgnData^); // Move output region to the origin place OffsetRgn(ARgn, kX, kY); FreeMem(RgnData); end; |