У меня есть объекты, которые я могу масштабировать вверх, вниз, влево, вправо, вверх-вправо, вниз. -left и т. д. Я написал всю логику для обработки всех этих случаев, даже для сгруппированных объектов. Проблема возникает, когда у нас есть вращение. Теперь вращение для отдельных объектов работает отлично, проблема заключается в логике при попытке пропорционально масштабировать все объекты внутри объекта, который масштабируется во время вращения.
Я написал простой проект, который мы можем использовать для демонстрации этой проблемы.
Позвольте мне показать вам пример.
Правильное поведение масштабирования один объект, даже с вращением:

Правильное масштабирование родительских и дочерних объектов без вращения:
[img]https:// i.sstatic.net/EDTBWpDZ.gif[/img]
Неправильное масштабирование родительских и дочерних объектов при вращении:

Последние пару дней я ломал голову над этой проблемой, и я очень дальше теперь, как вы можете видеть в третьей анимации, масштабирование, по крайней мере, правильное, когда я масштабирую его идеально по диагонали, но это заняло больше времени, чем должно, и прямо сейчас я застрял, потому что понятия не имею, как представить расчет в своей голове чтобы это корректно вело себя при масштабировании только в одном направлении.
Хотя это простой проект, из-за его характера он немного самостоятелен, поэтому я добавлю ссылка на исходный код, если кто-то хочет запустить его самостоятельно, но вот некоторый основной код:
Класс объектов:
Код: Выделить всё
public Dictionary Vector4Points { get; private set; }
public List Children = new List();
public OriginName GrabbedResizeOriginName;
private PointF _location;
public PointF Location
{
get
{
return _location;
}
set
{
PointF lastLocation = _location;
PointF moveDif = new PointF(value.X - lastLocation.X, value.Y - lastLocation.Y);
_location = value;
Origin = new PointF(Origin.X + moveDif.X, Origin.Y + moveDif.Y);
foreach(ObjRectangle objRectangle in Children)
{
objRectangle.MoveBy(moveDif);
}
Vector4Points = Get4VectorPoints();
}
}
private SizeF _size;
public SizeF Size
{
get
{
return _size;
}
set
{
float xDif = value.Width - _size.Width;
float yDif = value.Height - _size.Height;
switch (GrabbedResizeOriginName)
{
case OriginName.TopRight:
if (Rotation == 0f) // No rotation
Location = new PointF(Location.X, Location.Y - yDif);
else
{
PointF rotatedDelta = Utilities.RotatePoint(new PointF(0, -yDif), new PointF(0, 0), Rotation);
Location = new PointF(Location.X + rotatedDelta.X, Location.Y + rotatedDelta.Y);
}
break;
case OriginName.BottomLeft:
if (Rotation == 0f) // No rotation
Location = new PointF(Location.X - xDif, Location.Y);
else
{
PointF rotatedDelta = Utilities.RotatePoint(new PointF(-xDif, 0), new PointF(0, 0), Rotation);
Location = new PointF(Location.X + rotatedDelta.X, Location.Y + rotatedDelta.Y);
}
break;
case OriginName.TopLeft:
if (Rotation == 0f) // No rotation
Location = new PointF(Location.X - xDif, Location.Y - yDif);
else
{
PointF rotatedDelta = Utilities.RotatePoint(new PointF(-xDif, -yDif), new PointF(0, 0), Rotation);
Location = new PointF(Location.X + rotatedDelta.X, Location.Y + rotatedDelta.Y);
}
break;
default:
break;
}
_size = value;
Vector4Points = Get4VectorPoints();
}
}
public void MoveBy(PointF moveBy)
{
Location = new PointF(Location.X + moveBy.X, Location.Y + moveBy.Y);
}
public void ResizeParentAndChildren(SizeF newSize)
{
float scaleX = newSize.Width / Size.Width;
float scaleY = newSize.Height / Size.Height;
foreach (ObjRectangle child in Children)
{
child.GrabbedResizeOriginName = GrabbedResizeOriginName;
// Calculate the offset of the child from the parent's original origin
PointF childOffset = new PointF(child.Location.X - Location.X, child.Location.Y - Location.Y);
// Scale the offset based on the scaling factors
PointF scaledOffset = new PointF(childOffset.X * scaleX, childOffset.Y * scaleY);
// Calculate the new position of the child relative to the new origin of the parent
PointF newChildPosition = new PointF(Location.X + scaledOffset.X, Location.Y + scaledOffset.Y);
// Scale the size of the child
child.Size = new SizeF(child.Size.Width * scaleX, child.Size.Height * scaleY);
// Set the new position of the child
child.Location = newChildPosition;
}
Size = newSize;
}
public Dictionary Get4VectorPoints()
{
Dictionary points = new Dictionary
{
{ OriginName.TopLeft, Utilities.RotatePoint(new PointF(Location.X, Location.Y), Origin, Rotation) },
{ OriginName.TopRight, Utilities.RotatePoint(new PointF(Location.X + Size.Width, Location.Y), Origin, Rotation) },
{ OriginName.BottomRight, Utilities.RotatePoint(new PointF(Location.X + Size.Width, Location.Y + Size.Height), Origin, Rotation) },
{ OriginName.BottomLeft, Utilities.RotatePoint(new PointF(Location.X, Location.Y + Size.Height), Origin, Rotation) }
};
return points;
}
Код: Выделить всё
public static PointF RotatePoint(PointF point, PointF origin, double angleDegrees)
{
// Convert angle from degrees to radians
double angleRadians = angleDegrees * Math.PI / 180.0;
// Translate point so that origin is at (0, 0)
double translatedX = point.X - origin.X;
double translatedY = point.Y - origin.Y;
// Perform rotation
double rotatedX = translatedX * Math.Cos(angleRadians) - translatedY * Math.Sin(angleRadians);
double rotatedY = translatedX * Math.Sin(angleRadians) + translatedY * Math.Cos(angleRadians);
// Translate point back to its original position
rotatedX += origin.X;
rotatedY += origin.Y;
return new PointF((float)rotatedX, (float)rotatedY);
}
Код: Выделить всё
if (_resizingObject)
{
PointF rotatedDelta = Utilities.RotatePoint(mouseDelta, new PointF(0, 0), -geometryContainer.SelectedObject.Rotation);
float deltaX = rotatedDelta.X;
float deltaY = rotatedDelta.Y;
switch (geometryContainer.SelectedObject.GrabbedResizeOriginName)
{
case OriginName.TopLeft:
deltaX = -deltaX;
deltaY = -deltaY;
break;
case OriginName.TopRight:
deltaY = -deltaY;
break;
case OriginName.BottomLeft:
deltaX = -deltaX;
break;
default:
break;
}
geometryContainer.SelectedObject.ResizeParentAndChildren(new SizeF(geometryContainer.SelectedObject.Size.Width + deltaX, geometryContainer.SelectedObject.Size.Height + deltaY));
Invalidate();
}
https://uploadnow.io/f/GF2PQb7
Чтобы добавить объект, щелкните правой кнопкой мыши по форме.
Чтобы добавить дочерний объект, щелкните правой кнопкой мыши внутри уже существующего объекта.
Чтобы повернуть объект, вам придется нажать на него и использовать колесо прокрутки.
Заранее спасибо за ответы!
Подробнее здесь: https://stackoverflow.com/questions/784 ... en-rotated