diff --git a/components/tachart/tachartutils.pas b/components/tachart/tachartutils.pas index 2903639c83..03f003c15f 100644 --- a/components/tachart/tachartutils.pas +++ b/components/tachart/tachartutils.pas @@ -245,7 +245,8 @@ function ProjToRect( function RectIntersectsRect( var ARect: TDoubleRect; const AFixed: TDoubleRect): Boolean; -function RotatePoint(const APoint: TPoint; AAngle: Double): TPoint; +function RotatePoint(const APoint: TDoublePoint; AAngle: Double): TDoublePoint; overload; +function RotatePoint(const APoint: TPoint; AAngle: Double): TPoint; overload; function RoundChecked(A: Double): Integer; inline; function SafeInRange(AValue, ABound1, ABound2: Double): Boolean; @@ -693,6 +694,15 @@ begin RangesIntersect(a.Y, b.Y, AFixed.a.Y, AFixed.b.Y, a.Y, b.Y); end; +function RotatePoint(const APoint: TDoublePoint; AAngle: Double): TDoublePoint; +var + sa, ca: Extended; +begin + SinCos(AAngle, sa, ca); + Result.X := ca * APoint.X - sa * APoint.Y; + Result.Y := sa * APoint.X + ca * APoint.Y; +end; + function RotatePoint(const APoint: TPoint; AAngle: Double): TPoint; var sa, ca: Extended; diff --git a/components/tachart/taseries.pas b/components/tachart/taseries.pas index 0d8fcf9d6f..755629a4ff 100644 --- a/components/tachart/taseries.pas +++ b/components/tachart/taseries.pas @@ -895,12 +895,28 @@ var ARadius := Trunc(ARadius / (Max(Source.Extent.b.X, 0) + 1)); end; + function LabelExtraDist(AAngle: Double; AIndex: Integer): Double; + const + ALMOST_INF = 1e10; + var + z, e: TDoublePoint; + r: TDoubleRect; + begin + z := ZeroDoublePoint; + e := RotatePoint(DoublePoint(ALMOST_INF, 0), AAngle + Pi); + r.a.X := -labelWidths[AIndex] / 2; + r.b.X := -r.a.X; + r.a.Y := -labelHeights[AIndex] / 2; + r.b.Y := -r.a.Y; + LineIntersectsRect(z, e, r); + Result := Norm([e.X, e.Y]); + end; + var i, radius: Integer; prevAngle: Double = 0; d, angleStep, sliceCenterAngle: Double; c, center: TPoint; - sa, ca: Extended; prevLabelPoly: TPointArray = nil; const RAD_TO_DEG16 = 360 * 16; @@ -929,10 +945,7 @@ begin prevAngle += angleStep; if not Marks.IsMarkLabelsVisible then continue; - - // This is a crude approximation of label "radius", it may be improved. - SinCos(DegToRad(sliceCenterAngle / 16), sa, ca); - d := Max(Abs(labelWidths[i] * ca), Abs(labelHeights[i] * sa)) / 2; + d := LabelExtraDist(DegToRad(sliceCenterAngle / 16), i); Marks.DrawLabel( ACanvas, LineEndPoint(c, sliceCenterAngle, radius),