Пропорциональное масштабирование объектов внутри другого объекта при вращении.C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Пропорциональное масштабирование объектов внутри другого объекта при вращении.

Сообщение Anonymous »

Я пишу программу для маркировки и столкнулся с очень сложной математической проблемой.
У меня есть объекты, которые я могу масштабировать вверх, вниз, влево, вправо, вверх-вправо, вниз. -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
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Пропорциональное масштабирование объектов внутри другого объекта при вращении.
    Anonymous » » в форуме C#
    0 Ответы
    52 Просмотры
    Последнее сообщение Anonymous
  • Как избежать изменения размера других объектов при вращении объекта?
    Anonymous » » в форуме CSS
    0 Ответы
    16 Просмотры
    Последнее сообщение Anonymous
  • При вращении объекта вокруг целевого объекта радиус не выглядит очень точным на 100%. как сделать радиус точным?
    Anonymous » » в форуме C#
    0 Ответы
    94 Просмотры
    Последнее сообщение Anonymous
  • Проблемы при вращении объекта вокруг двух осей (C#)
    Anonymous » » в форуме C#
    0 Ответы
    23 Просмотры
    Последнее сообщение Anonymous
  • Проблемы при вращении объекта вокруг двух осей (C#)
    Anonymous » » в форуме C#
    0 Ответы
    20 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»