Skip to content

Commit

Permalink
[V2] Fix HelixToolkit.Wpf.TextVisual3D display wrong size when apply …
Browse files Browse the repository at this point in the history
…Angle!=0 (#2210)

* Fix HelixToolkit.Wpf.TextVisual3D display wrong size when apply Angle!=0

* Fix consistancy rotate couter-clockwise
  • Loading branch information
MauNguyenVan authored May 8, 2024
1 parent 96cf99b commit 557375f
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ public string Text
}

/// <summary>
/// The rotation angle of text clockwise, in degrees.
/// The rotation angle of the text in counter-clockwise, in degrees.
/// </summary>
public double Angle
{
Expand All @@ -321,10 +321,6 @@ public double Angle
}
set
{
if (value != 0 && rotateTransform is null)
{
rotateTransform = new RotateTransform();
}
this.SetValue(AngleProperty, value);
}
}
Expand Down Expand Up @@ -379,16 +375,26 @@ private void VisualChanged()
}
: textBlock;

// Only prevent assign when angle == 0, it is equal origin value
// https://stackoverflow.com/questions/10329298/performance-impact-of-applying-either-layouttransform-vs-rendertransform
if (Angle != 0 || (rotateTransform != null && rotateTransform.Angle != Angle))
/*
* In WPF 2D, rotates an object clockwise about a specified point in a 2-D x-y coordinate system.
* In WPF 3D is a right-handed system, which means that a positive angle value for a rotation results in a counter-clockwise rotation about the axis.
* So, to make consistent behavior with the default 3D coordinate system, a positive angle value for a rotation will rotate in a counter-clockwise
*
* Only prevent assign when angle == 0, it is equal origin value
* https://stackoverflow.com/questions/10329298/performance-impact-of-applying-either-layouttransform-vs-rendertransform
*/
double angle = -this.Angle;
if (angle != 0 || (rotateTransform != null && rotateTransform.Angle != angle))
{
rotateTransform.Angle = Angle;
rotateTransform ??= new RotateTransform();
rotateTransform.Angle = angle;
element.LayoutTransform = rotateTransform;
}

element.Measure(new Size(1000, 1000));
element.Arrange(new Rect(element.DesiredSize));
element.RenderSize = element.DesiredSize;

var rtb = new RenderTargetBitmap(
(int)element.ActualWidth + 1, (int)element.ActualHeight + 1, 96, 96, PixelFormats.Pbgra32);
rtb.Render(element);
Expand Down
85 changes: 57 additions & 28 deletions Source/HelixToolkit.Wpf.Shared/Visual3Ds/Text/TextVisual3D.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public bool IsFlipped
/// </summary>
public static readonly DependencyProperty AngleProperty =
DependencyProperty.Register(
"AngleProperty",
"AngleProperty",
typeof(double),
typeof(TextVisual3D),
new UIPropertyMetadata(0.0, VisualChanged));
Expand Down Expand Up @@ -434,7 +434,7 @@ public VerticalAlignment VerticalAlignment
}

/// <summary>
/// The rotation angle of text clockwise, in degrees.
/// The rotation angle of the text in counter-clockwise, in degrees.
/// </summary>
public double Angle
{
Expand All @@ -444,15 +444,14 @@ public double Angle
}
set
{
if (value != 0 && rotateTransform is null)
{
rotateTransform = new RotateTransform();
}
this.SetValue(AngleProperty, value);
}
}

private RotateTransform rotateTransform = null;
/// <summary>
/// WPF 3D is a right-handed system, which means that a positive angle value for a rotation results in a counter-clockwise rotation about the axis.
/// </summary>
private RotateTransform3D rotateTransform = null;

/// <summary>
/// The visual changed.
Expand Down Expand Up @@ -481,12 +480,12 @@ private void VisualChanged()

// First we need a textblock containing the text of our label
var textBlock = new TextBlock(new Run(this.Text))
{
Foreground = this.Foreground,
Background = this.Background,
FontWeight = this.FontWeight,
Padding = this.Padding
};
{
Foreground = this.Foreground,
Background = this.Background,
FontWeight = this.FontWeight,
Padding = this.Padding
};
if (this.FontFamily != null)
{
textBlock.FontFamily = this.FontFamily;
Expand All @@ -499,23 +498,16 @@ private void VisualChanged()
var element = this.BorderBrush != null
? (FrameworkElement)
new Border
{
BorderBrush = this.BorderBrush,
BorderThickness = this.BorderThickness,
Child = textBlock
}
{
BorderBrush = this.BorderBrush,
BorderThickness = this.BorderThickness,
Child = textBlock
}
: textBlock;

// Only prevent assign when angle == 0, it is equal origin value
// https://stackoverflow.com/questions/10329298/performance-impact-of-applying-either-layouttransform-vs-rendertransform
if (Angle != 0 || (rotateTransform != null && rotateTransform.Angle != Angle))
{
rotateTransform.Angle = Angle;
element.LayoutTransform = rotateTransform;
}
element.Measure(new Size(1000, 1000));
element.Arrange(new Rect(element.DesiredSize));
element.RenderSize = element.DesiredSize;
//element.RenderSize = element.DesiredSize;

Material material;
if (this.FontSize > 0)
Expand All @@ -537,7 +529,7 @@ private void VisualChanged()
var textDirection = this.TextDirection;
var updirection = this.UpDirection;
var height = this.Height;

UpdateDirectionsByRotationTransform(ref textDirection, ref updirection);
// Set horizontal alignment factor
var xa = -0.5;
if (this.HorizontalAlignment == HorizontalAlignment.Left)
Expand Down Expand Up @@ -620,8 +612,45 @@ private void VisualChanged()
}

this.Content = new GeometryModel3D(mg, material);
// http://www.ericsink.com/wpf3d/4_Text.html
}

// http://www.ericsink.com/wpf3d/4_Text.html
/// <summary>
/// Update directions when applying <see cref="Angle"/> value.
/// </summary>
/// <param name="textDirection"></param>
/// <param name="updirection"></param>
private void UpdateDirectionsByRotationTransform(ref Vector3D textDirection, ref Vector3D updirection)
{
Vector3D n = Vector3D.CrossProduct(this.TextDirection, this.UpDirection);
n.Normalize();
if (rotateTransform is null)
{
if (this.Angle != 0)
rotateTransform = new RotateTransform3D(new AxisAngleRotation3D(n, this.Angle), this.Position);
}
else
{
if (rotateTransform.CenterX != this.Position.X
|| rotateTransform.CenterY != this.Position.Y
|| rotateTransform.CenterZ != this.Position.Z)
{
rotateTransform.CenterX = this.Position.X;
rotateTransform.CenterY = this.Position.Y;
rotateTransform.CenterZ = this.Position.Z;
}
AxisAngleRotation3D axisAngle = (AxisAngleRotation3D)rotateTransform.Rotation;
if (axisAngle.Axis != n || axisAngle.Angle != this.Angle)
{
axisAngle.Axis = n;
axisAngle.Angle = this.Angle;
}
}
if (rotateTransform != null)
{
textDirection = rotateTransform.Transform(textDirection);
updirection = rotateTransform.Transform(updirection);
}
}
}
}

0 comments on commit 557375f

Please sign in to comment.