Modify Spacing control behavior
This commit is contained in:
parent
6c5d7732ff
commit
06fbe3a922
2 changed files with 218 additions and 50 deletions
|
@ -898,6 +898,35 @@ TPointD calculatePointOnLine(TPointD firstPoint, double rotation,
|
|||
return refPoint;
|
||||
}
|
||||
|
||||
double calculateSpacing(PerspectiveType perspectiveType, TPointD spacingPos,
|
||||
TPointD rotationPos, double rotation,
|
||||
TPointD centerPoint) {
|
||||
double newSpace;
|
||||
|
||||
double dx = spacingPos.x - centerPoint.x;
|
||||
double dy = spacingPos.y - centerPoint.y;
|
||||
double distance = std::sqrt(std::pow(dx, 2) + std::pow(dy, 2));
|
||||
double angle = std::atan2(dy, dx) / (3.14159 / 180);
|
||||
|
||||
if (perspectiveType == PerspectiveType::VanishingPoint) {
|
||||
if (angle < 0) angle += 360;
|
||||
|
||||
double drx = rotationPos.x - centerPoint.x;
|
||||
double dry = rotationPos.y - centerPoint.y;
|
||||
double rangle = std::atan2(dry, drx) / (3.14159 / 180);
|
||||
if (rangle < 0) rangle += 360;
|
||||
|
||||
newSpace = std::abs(rangle - angle);
|
||||
if (newSpace > 180) newSpace = 360 - newSpace;
|
||||
} else { // Assumed Line
|
||||
angle -= rotation;
|
||||
TPointD normPos = calculatePointOnLine(centerPoint, angle, distance);
|
||||
newSpace = std::abs(normPos.y - centerPoint.y);
|
||||
}
|
||||
|
||||
return newSpace;
|
||||
}
|
||||
|
||||
void PerspectiveTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
|
||||
if (!m_perspectiveObjs.size()) return;
|
||||
|
||||
|
@ -952,6 +981,7 @@ void PerspectiveTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
|
|||
|
||||
TPointD centerPoint = mainObj->getCenterPoint();
|
||||
TPointD rotationPos = mainObj->getRotationPos();
|
||||
TPointD spacingPos = mainObj->getSpacingPos();
|
||||
TPointD dPos = usePos - m_firstPos;
|
||||
double dAngle = 0.0;
|
||||
double dSpace = 0.0;
|
||||
|
@ -969,19 +999,37 @@ void PerspectiveTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
|
|||
|
||||
dAngle = nangle - oangle;
|
||||
} else if (m_isSpacing) {
|
||||
double da = std::sqrt(std::pow(centerPoint.x - m_firstPos.x, 2) +
|
||||
std::pow(centerPoint.y - m_firstPos.y, 2));
|
||||
double db = std::sqrt(std::pow(centerPoint.x - usePos.x, 2) +
|
||||
std::pow(centerPoint.y - usePos.y, 2));
|
||||
dSpace = db - da;
|
||||
TPointD newSpacingPos = spacingPos + dPos;
|
||||
double newSpace;
|
||||
|
||||
if (e.isAltPressed()) {
|
||||
m_totalChange += dSpace;
|
||||
if (std::abs(m_totalChange) >= 10) {
|
||||
dSpace = m_totalChange < 0 ? -10 : 10;
|
||||
m_totalChange = 0;
|
||||
} else
|
||||
dSpace = 0;
|
||||
if (mainObj->getType() == PerspectiveType::VanishingPoint) {
|
||||
double dox = spacingPos.x - centerPoint.x;
|
||||
double doy = spacingPos.y - centerPoint.y;
|
||||
double oangle = std::atan2(doy, dox) / (3.14159 / 180);
|
||||
|
||||
double dnx = newSpacingPos.x - centerPoint.x;
|
||||
double dny = newSpacingPos.y - centerPoint.y;
|
||||
double nangle = std::atan2(dny, dnx) / (3.14159 / 180);
|
||||
dAngle = nangle - oangle;
|
||||
if (nangle < 0) nangle += 360;
|
||||
|
||||
double drx = rotationPos.x - centerPoint.x;
|
||||
double dry = rotationPos.y - centerPoint.y;
|
||||
double rangle = std::atan2(dry, drx) / (3.14159 / 180);
|
||||
if (rangle < 0) rangle += 360;
|
||||
|
||||
newSpace = std::abs(rangle - nangle);
|
||||
if (newSpace > 180) newSpace = 360 - newSpace;
|
||||
dSpace = newSpace - mainObj->getSpacing();
|
||||
} else { // Assumed Line
|
||||
double dx = newSpacingPos.x - centerPoint.x;
|
||||
double dy = newSpacingPos.y - centerPoint.y;
|
||||
double distance = std::sqrt(std::pow(dx, 2) + std::pow(dy, 2));
|
||||
double angle = std::atan2(dy, dx) / (3.14159 / 180);
|
||||
angle -= mainObj->getRotation();
|
||||
TPointD normPos = calculatePointOnLine(centerPoint, angle, distance);
|
||||
newSpace = std::abs(normPos.y - centerPoint.y);
|
||||
dSpace = newSpace - mainObj->getSpacing();
|
||||
}
|
||||
} else if (!m_isShifting &&
|
||||
mainObj->getType() == PerspectiveType::VanishingPoint) {
|
||||
|
@ -1011,16 +1059,24 @@ void PerspectiveTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
|
|||
}
|
||||
mainObj->setCenterPoint(centerPoint);
|
||||
|
||||
// Move Rotation control or recalculate Rotation Angle
|
||||
if (mainObj->isHorizon() && e.isAltPressed())
|
||||
if (mainObj->isHorizon() && e.isAltPressed()) {
|
||||
// Move Rotation/Space controls to maintain angle/spacing
|
||||
mainObj->setRotationPos(rotationPos + dPosCP);
|
||||
else {
|
||||
mainObj->setSpacingPos(spacingPos + dPosCP);
|
||||
} else {
|
||||
// Recalculate Angle
|
||||
double dx = rotationPos.x - newCenterPoint.x;
|
||||
double dy = rotationPos.y - newCenterPoint.y;
|
||||
double newAngle = std::atan2(dy, dx) / (3.14159 / 180);
|
||||
if (mainObj->getType() == PerspectiveType::VanishingPoint)
|
||||
newAngle += 90;
|
||||
mainObj->setRotation(newAngle);
|
||||
|
||||
// Recalculate Spacing
|
||||
double newSpacing =
|
||||
calculateSpacing(mainObj->getType(), spacingPos, rotationPos,
|
||||
mainObj->getRotation(), centerPoint);
|
||||
mainObj->setSpacing(newSpacing);
|
||||
}
|
||||
|
||||
// Check Right Handle
|
||||
|
@ -1050,16 +1106,24 @@ void PerspectiveTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
|
|||
}
|
||||
mainObj->setCenterPoint(centerPoint);
|
||||
|
||||
// Move Rotation control or recalculate Rotation Angle
|
||||
if (mainObj->isHorizon() && e.isAltPressed())
|
||||
if (mainObj->isHorizon() && e.isAltPressed()) {
|
||||
// Move Rotation/Space controls to maintain angle/spacing;
|
||||
mainObj->setRotationPos(rotationPos + dPosCP);
|
||||
else {
|
||||
mainObj->setSpacingPos(spacingPos + dPosCP);
|
||||
} else {
|
||||
// Recalculate Angle
|
||||
double dx = rotationPos.x - newCenterPoint.x;
|
||||
double dy = rotationPos.y - newCenterPoint.y;
|
||||
double newAngle = std::atan2(dy, dx) / (3.14159 / 180);
|
||||
if (mainObj->getType() == PerspectiveType::VanishingPoint)
|
||||
newAngle += 90;
|
||||
mainObj->setRotation(newAngle);
|
||||
|
||||
// Recalculate Spacing
|
||||
double newSpacing =
|
||||
calculateSpacing(mainObj->getType(), spacingPos, rotationPos,
|
||||
mainObj->getRotation(), centerPoint);
|
||||
mainObj->setSpacing(newSpacing);
|
||||
}
|
||||
|
||||
// Check Left Handle
|
||||
|
@ -1096,6 +1160,7 @@ void PerspectiveTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
|
|||
PerspectiveObject *obj = m_perspectiveObjs[*it];
|
||||
TPointD objCenterPoint = obj->getCenterPoint();
|
||||
TPointD rotationPos = obj->getRotationPos();
|
||||
TPointD spacingPos = obj->getSpacingPos();
|
||||
|
||||
if (m_isShifting)
|
||||
obj->shiftPerspectiveObject(dPos);
|
||||
|
@ -1118,15 +1183,23 @@ void PerspectiveTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
|
|||
TPointD newCenterPoint = objCenterPoint + dPos;
|
||||
obj->setCenterPoint(newCenterPoint);
|
||||
|
||||
// Move Rotation control or recalculate Rotation Angle
|
||||
if (obj->isHorizon() && e.isAltPressed())
|
||||
if (obj->isHorizon() && e.isAltPressed()) {
|
||||
// Move Rotation/Space controls to maintain angle/spacing
|
||||
obj->setRotationPos(rotationPos + dPos);
|
||||
else {
|
||||
obj->setSpacingPos(spacingPos + dPos);
|
||||
} else {
|
||||
// Recalculate Angle
|
||||
double dx = rotationPos.x - newCenterPoint.x;
|
||||
double dy = rotationPos.y - newCenterPoint.y;
|
||||
double newAngle = std::atan2(dy, dx) / (3.14159 / 180);
|
||||
if (obj->getType() == PerspectiveType::VanishingPoint) newAngle += 90;
|
||||
obj->setRotation(newAngle);
|
||||
|
||||
// Recalculate Spacing
|
||||
double newSpacing =
|
||||
calculateSpacing(obj->getType(), spacingPos, rotationPos,
|
||||
obj->getRotation(), objCenterPoint);
|
||||
obj->setSpacing(newSpacing);
|
||||
}
|
||||
|
||||
// Also Move Left and Right Handles
|
||||
|
@ -1166,12 +1239,108 @@ void PerspectiveTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
|
|||
}
|
||||
obj->setRotation(rotation + dAngle);
|
||||
obj->setRotationPos(newRotationPos);
|
||||
|
||||
// Move Spacing control to keep current spacing
|
||||
distance = std::sqrt(std::pow((objCenterPoint.x - spacingPos.x), 2) +
|
||||
std::pow((objCenterPoint.y - spacingPos.y), 2));
|
||||
double dx = spacingPos.x - objCenterPoint.x;
|
||||
double dy = spacingPos.y - objCenterPoint.y;
|
||||
double angle = std::atan2(dy, dx) / (3.14159 / 180);
|
||||
double nangle = angle + dAngle;
|
||||
|
||||
TPointD newSpacingPos =
|
||||
calculatePointOnLine(objCenterPoint, nangle, distance);
|
||||
|
||||
obj->setSpacingPos(newSpacingPos);
|
||||
} else if (m_isSpacing) {
|
||||
double spacing = obj->getSpacing();
|
||||
obj->setSpacing(spacing + dSpace);
|
||||
TPointD newSpacingPos = spacingPos + dPos;
|
||||
double delta = dSpace;
|
||||
|
||||
TPointD spacingPos = obj->getSpacingPos();
|
||||
obj->setSpacingPos(spacingPos + dPos);
|
||||
TPointD pos = obj == mainObj ? usePos : spacingPos;
|
||||
double dx = pos.x - objCenterPoint.x;
|
||||
double dy = pos.y - objCenterPoint.y;
|
||||
double distance = std::sqrt(std::pow(dx, 2) + std::pow(dy, 2));
|
||||
double angle = std::atan2(dy, dx) / (3.14159 / 180);
|
||||
|
||||
if (e.isAltPressed()) {
|
||||
double space = tfloor((int)(spacing + delta + 5), 10);
|
||||
delta = space - spacing;
|
||||
|
||||
if (obj->getType() == PerspectiveType::VanishingPoint) {
|
||||
double dx2 = newSpacingPos.x - objCenterPoint.x;
|
||||
double dy2 = newSpacingPos.y - objCenterPoint.y;
|
||||
double angle2 = std::atan2(dy2, dx2) / (3.14159 / 180);
|
||||
if (angle2 < 0) angle2 += 360;
|
||||
|
||||
double drx = rotationPos.x - objCenterPoint.x;
|
||||
double dry = rotationPos.y - objCenterPoint.y;
|
||||
double rangle = std::atan2(dry, drx) / (3.14159 / 180);
|
||||
if (rangle < 0) rangle += 360;
|
||||
|
||||
double diffAngle = angle2 - rangle;
|
||||
if (diffAngle < 0) diffAngle += 360;
|
||||
|
||||
double newAngle = spacing + delta + 270;
|
||||
if (newAngle < 0) newAngle += 360;
|
||||
|
||||
if (diffAngle > 180) {
|
||||
newAngle *= -1;
|
||||
distance *= -1;
|
||||
}
|
||||
newAngle += obj->getRotation();
|
||||
|
||||
newSpacingPos =
|
||||
calculatePointOnLine(objCenterPoint, newAngle, distance);
|
||||
} else { // Assumed Line
|
||||
angle -= obj->getRotation();
|
||||
TPointD normPos =
|
||||
calculatePointOnLine(objCenterPoint, angle, distance);
|
||||
dy = spacing + delta;
|
||||
if ((normPos.y - objCenterPoint.y) < 0) dy *= -1;
|
||||
dx = normPos.x - objCenterPoint.x;
|
||||
distance = std::sqrt(std::pow(dx, 2) + std::pow(dy, 2));
|
||||
angle = std::atan2(dy, dx) / (3.14159 / 180);
|
||||
angle += obj->getRotation();
|
||||
newSpacingPos =
|
||||
calculatePointOnLine(objCenterPoint, angle, distance);
|
||||
}
|
||||
|
||||
if (obj == mainObj) usePos = delta == 0 ? m_firstPos : newSpacingPos;
|
||||
|
||||
} else if (obj != mainObj) {
|
||||
if (obj->getType() == PerspectiveType::VanishingPoint) {
|
||||
double nangle = angle + dAngle;
|
||||
|
||||
newSpacingPos =
|
||||
calculatePointOnLine(objCenterPoint, nangle, distance);
|
||||
if (nangle < 0) nangle += 360;
|
||||
|
||||
double drx = rotationPos.x - objCenterPoint.x;
|
||||
double dry = rotationPos.y - objCenterPoint.y;
|
||||
double rangle = std::atan2(dry, drx) / (3.14159 / 180);
|
||||
if (rangle < 0) rangle += 360;
|
||||
|
||||
double newSpace = std::abs(rangle - nangle);
|
||||
if (newSpace > 180) newSpace = 360 - newSpace;
|
||||
delta = newSpace - spacing;
|
||||
} else { // Assumed line
|
||||
angle -= obj->getRotation();
|
||||
TPointD normPos =
|
||||
calculatePointOnLine(objCenterPoint, angle, distance);
|
||||
dy = spacing + delta;
|
||||
if ((normPos.y - objCenterPoint.y) < 0) dy *= -1;
|
||||
dx = normPos.x - objCenterPoint.x;
|
||||
distance = std::sqrt(std::pow(dx, 2) + std::pow(dy, 2));
|
||||
angle = std::atan2(dy, dx) / (3.14159 / 180);
|
||||
angle += obj->getRotation();
|
||||
newSpacingPos =
|
||||
calculatePointOnLine(objCenterPoint, angle, distance);
|
||||
}
|
||||
}
|
||||
|
||||
obj->setSpacing(spacing + delta);
|
||||
obj->setSpacingPos(newSpacingPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1541,6 +1710,8 @@ void VanishingPointPerspective::draw(SceneViewer *viewer, TRectD cameraRect) {
|
|||
std::sqrt(std::pow(distance, 2) + std::pow(distance, 2));
|
||||
|
||||
double step = getSpacing();
|
||||
step = std::min(step, getMaxSpacing());
|
||||
step = std::max(step, getMinSpacing());
|
||||
int rays = isHorizon() ? totalDistance : (360 / step);
|
||||
if (rays == 0) rays = 1;
|
||||
if (!isHorizon()) step = 360.0 / (double)rays;
|
||||
|
@ -1721,18 +1892,14 @@ void LinePerspective::draw(SceneViewer *viewer, TRectD cameraRect) {
|
|||
if (isParallel()) {
|
||||
TPointD above = p;
|
||||
TPointD below = p;
|
||||
double distance = 0.0;
|
||||
double step = getSpacing();
|
||||
step = std::min(step, getMaxSpacing());
|
||||
step = std::max(step, getMinSpacing());
|
||||
double distanceFromCP = step;
|
||||
|
||||
double stepspeed = isHorizon() ? 1.5 : 1.0;
|
||||
|
||||
double distanceFromCP = 0.0;
|
||||
|
||||
while (std::abs(distanceFromCP) <= totalDistance) {
|
||||
distance += (step * stepspeed);
|
||||
step = step * stepspeed;
|
||||
|
||||
distanceFromCP = distance / Stage::standardDpi * Stage::inch;
|
||||
|
||||
while (distanceFromCP <= totalDistance) {
|
||||
if (!isHorizon()) {
|
||||
above.y = p.y + (std::cos(-theta) * distanceFromCP);
|
||||
above.x = p.x + (std::sin(-theta) * distanceFromCP);
|
||||
|
@ -1750,6 +1917,9 @@ void LinePerspective::draw(SceneViewer *viewer, TRectD cameraRect) {
|
|||
end.x = below.x + xLength;
|
||||
end.y = below.y + yLength;
|
||||
tglDrawSegment(start, end);
|
||||
|
||||
distanceFromCP += (step * stepspeed);
|
||||
step = step * stepspeed;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,14 +56,12 @@ public:
|
|||
void setParallel(bool isParallel) { m_parallel = isParallel; }
|
||||
bool isParallel() { return m_parallel; }
|
||||
|
||||
void setSpacing(double space) {
|
||||
m_spacing = space;
|
||||
m_spacing = std::min(m_spacing, m_maxSpacing);
|
||||
m_spacing = std::max(m_spacing, m_minSpacing);
|
||||
}
|
||||
void setSpacing(double space) { m_spacing = space; }
|
||||
virtual double getSpacing() { return m_spacing; }
|
||||
void setMinSpacing(int minSpace) { m_minSpacing = minSpace; }
|
||||
virtual double getMinSpacing() { return m_minSpacing; }
|
||||
void setMaxSpacing(int maxSpace) { m_maxSpacing = maxSpace; }
|
||||
virtual double getMaxSpacing() { return m_maxSpacing; }
|
||||
|
||||
void setHorizon(bool isHorizon) { m_horizon = isHorizon; }
|
||||
bool isHorizon() { return m_horizon; }
|
||||
|
@ -79,7 +77,7 @@ protected:
|
|||
TPointD m_centerPoint;
|
||||
double m_rotation;
|
||||
bool m_parallel;
|
||||
double m_spacing, m_minSpacing = 1.0, m_maxSpacing = 250.0;
|
||||
double m_spacing, m_minSpacing = 1.0, m_maxSpacing = UINT_MAX;
|
||||
bool m_horizon;
|
||||
double m_opacity;
|
||||
TPixel32 m_color;
|
||||
|
@ -349,20 +347,20 @@ class VanishingPointPerspective final : public PerspectiveObject {
|
|||
public:
|
||||
VanishingPointPerspective()
|
||||
: PerspectiveObject(PerspectiveType::VanishingPoint) {
|
||||
setSpacing(10);
|
||||
setSpacing(27);
|
||||
setParallel(false);
|
||||
setMaxSpacing(180);
|
||||
setRotationPos(TPointD(0, -40));
|
||||
setSpacingPos(TPointD(40, -40));
|
||||
setSpacingPos(TPointD(20, -40));
|
||||
};
|
||||
~VanishingPointPerspective(){};
|
||||
|
||||
void draw(SceneViewer *viewer, TRectD cameraRect) override;
|
||||
|
||||
double getSpacing() override {
|
||||
if (isHorizon()) return std::min(m_spacing, 90.0);
|
||||
double getMaxSpacing() override {
|
||||
if (isHorizon()) return 90.0;
|
||||
|
||||
return m_spacing;
|
||||
return m_maxSpacing;
|
||||
}
|
||||
|
||||
TPointD getReferencePoint(TPointD firstPoint) override {
|
||||
|
@ -377,7 +375,7 @@ public:
|
|||
class LinePerspective final : public PerspectiveObject {
|
||||
public:
|
||||
LinePerspective() : PerspectiveObject(PerspectiveType::Line) {
|
||||
setSpacing(30);
|
||||
setSpacing(40);
|
||||
};
|
||||
~LinePerspective(){};
|
||||
|
||||
|
|
Loading…
Reference in a new issue