Russian Qt Forum
Май 16, 2024, 15:17 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: Размеры прямоугольника в который вписана дуга.  (Прочитано 22218 раз)
supertux
Гость
« Ответ #15 : Декабрь 21, 2015, 17:11 »

Точка A это текущее положение резца, так понимаю...
Можете продемонстрировать для второго примера что было бы, если я ввёл
G03 X35 Y20 I-15 J20 ?

Да, точка А известна, т. к. является текущим положением инструмента. G02 - рисуем по часовой стрелке, G03 - против.

Пример с I -15:

« Последнее редактирование: Декабрь 21, 2015, 17:16 от supertux » Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #16 : Декабрь 21, 2015, 17:24 »

У вас CA и CB не равны по длине. Полученная кривая не является дугой окружности...
Имея 2 фиксированные точки на плоскости, вы можете соединить их дугой, центр которой будет лежать на перпендикуляре к хорде, проходящим через её середину
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #17 : Декабрь 21, 2015, 17:26 »

Я хочу сказать, что нельзя задать любой центр. И в предыдущем примере задав неверный центр мы не попадём из А в В.
Записан
supertux
Гость
« Ответ #18 : Декабрь 21, 2015, 17:35 »

Я хочу сказать, что нельзя задать любой центр. И в предыдущем примере задав неверный центр мы не попадём из А в В.

То что вы говорите, это безусловно верно, НО!
Я всего навсего привел пример, что будет если сделать I -15, чисто теоретически. Сам G код пишется не вручную, а генерируется в nest-программах из DXF файлов таким образом, что CA и CB будут всегда равны.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #19 : Декабрь 21, 2015, 17:39 »

Ааа. Тогда другое дело.  Улыбающийся
А как вы понимаете, какой вариант дуги рассматривается, по часовой или против?
Записан
supertux
Гость
« Ответ #20 : Декабрь 21, 2015, 17:53 »

А как вы понимаете, какой вариант дуги рассматривается, по часовой или против?

Может я не совсем понял вопроса...  При плазменной резке металла, внешний контур обычно режется по часовой, а отверстия в этой детали - против, в связи с тем, что лучшее качество кромки  всегда справа по направлению режущего инструмента.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #21 : Декабрь 21, 2015, 17:55 »

Ладно, это уже мелочи реализации, забудем.
Как я уже вам сказал, вам необходимо взять и нарисовать квадрат и отрезать всё лишнее.
Резать по алгоритму:
Если дуга проходит через квадрант, то сторону квадрата, на которой лежит точка не двигаем. Остальные же модифицируем. Ниже попытался выразить мысли в рисунке.
Записан
supertux
Гость
« Ответ #22 : Декабрь 21, 2015, 18:06 »

Нарисовать это где, в QGraphicscene?  Просто я не совсем представляю как оно должно реализовываться. Если возможно, покажите мне кусочек кода, так нагляднее.
Записан
popper
Гость
« Ответ #23 : Декабрь 21, 2015, 18:45 »

Направление отрисовки в drawArc определяется знаком параметра spanAngle. Может ли в программу  отрисовки быть передан параметр, определяющий направление вращения дополнительно к передаваемым координатам трех точек? Я имею ввиду, передать число +1 или -1 в зависимости от вида инструкции G03 или G02.
Записан
supertux
Гость
« Ответ #24 : Декабрь 21, 2015, 19:03 »

А действительно... Может ли? Я новичок в программировании графики в Qt. Только  3 дня прошло, как я взялся это писать. Смеющийся Могу многих нюансов не знать. Может еще spanangle и startangle вычислять придется (это если я правильно понял, spanangle - централный угол). Если вычилсить радиус дуги и центральный угол, то тогда можно будет вычислить высоту/ширину прямоугольника по формуле:

H=R-R*cos(a/2)
L=2*R*sin(a/2)
a - угол
R - радиус
H,L - стороны прямоугольника

« Последнее редактирование: Декабрь 21, 2015, 19:14 от supertux » Записан
ibnz
Гость
« Ответ #25 : Декабрь 21, 2015, 23:34 »

Предполагая, что оперируем с меньшей возможной дугой:

Код:
#include <QCoreApplication>
#include <cmath>
#include <QTransform>
#include <QDebug>

QRectF getArcBoundingRect(const QPointF &p1, const QPointF &p2, const QPointF &center)
{
    QTransform centerTranslate = QTransform::fromTranslate(-center.x(), -center.y());

    //в систему координат центра кривизны
    QPointF pp1 = centerTranslate.map(p1);
    QPointF pp2 = centerTranslate.map(p2);

    // можно выкинуть, если не нужна проверка на равенство радиусов
    {
        qreal radius1 = std::hypot(pp1.x(), pp1.y());
        qreal radius2 = std::hypot(pp2.x(), pp2.y());
        if (!qFuzzyCompare(radius1, radius2)) {
           qCritical() << Q_FUNC_INFO << " radius1 != radius2";
           return QRectF();
        }
    }

    qreal radius = std::hypot(pp1.x(), pp1.y());;
    QPointF topLeft = QPointF(qMin(pp1.x(), pp2.x()), qMax(pp1.y(), pp2.y()));
    QPointF bottomRight = QPointF(qMax(pp1.x(), pp2.x()), qMin(pp1.y(), pp2.y()));
    if (pp1.x() * pp2.x() < 0) {
        if(topLeft.y() > 0){
            topLeft.ry() = qMax(topLeft.y(), radius);
        }
        if(bottomRight.y() < 0){
            bottomRight.ry() = qMin(bottomRight.y(), -radius);
        }
    }
    if (pp1.y() * pp2.y() < 0) {
        if(topLeft.x() < 0){
            topLeft.rx() = qMin(topLeft.x(), -radius);
        }
        if(bottomRight.x() > 0){
            bottomRight.rx() = qMax(bottomRight.x(), radius);
        }
    }

    // в исходную систему координат
    auto defaultTransform = centerTranslate.inverted();
    topLeft = defaultTransform.map(topLeft);
    bottomRight = defaultTransform.map(bottomRight);

    return QRectF(topLeft, bottomRight);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug() << getArcBoundingRect(QPointF(3, -5), QPointF(5, -3), QPointF(2,-2));
    return a.exec();
}



« Последнее редактирование: Декабрь 21, 2015, 23:38 от ibnz » Записан
supertux
Гость
« Ответ #26 : Декабрь 22, 2015, 11:21 »

Перевел код на Python (т. к. пишу на нем):

Код:
from PyQt5.QtCore import *
from PyQt5.QtGui import QTransform
from math import hypot

def getArcBoundingRect(p1, p2, center):
    centerTranslate = QTransform.fromTranslate(-center.x(), -center.y())
    pp1 = QPointF(centerTranslate.map(p1))
    pp2 = QPointF(centerTranslate.map(p2))
   
#Проверка на равенство радиусов
    radius1 = hypot(pp1.x(), pp1.y())
    radius2 = hypot(pp2.x(), pp2.y())
    if not qFuzzyCompare(radius1, radius2):
        qCritical(" radius1 != radius2")
        #return QRectF()

    radius = hypot(pp1.x(), pp1.y())
    topLeft = QPointF(min(pp1.x(), pp2.x()), max(pp1.y(), pp2.y()))
    bottomRight = QPointF(max(pp1.x(), pp2.x()), min(pp1.y(), pp2.y()))
    if (pp1.x() * pp2.x() < 0):
        if (topLeft.y() > 0):
            topLeft.ry = max(topLeft.y(), radius)
        if (bottomRight.y() < 0):
            bottomRight.ry = min(bottomRight.y(), -radius)
   
    if (pp1.y() * pp2.y() < 0):
        if (topLeft.x() < 0):
            topLeft.rx = min(topLeft.x(), -radius)
        if(bottomRight.x() > 0):
            bottomRight.rx = max(bottomRight.x(), radius)
           
    #В исходную систему координат
    defaultTransform = centerTranslate.inverted()
    topLeft = defaultTransform.map(topLeft)
    bottomRight = defaultTransform.map(bottomRight)

    return QRectF(topLeft, bottomRight)

i = 20.0
j = -5.0
aX = 6.31
aY = 5.773
bX = 20.53
bY = 19.836
a = QPointF(aX, aY)
b = QPointF(bX, bY)
c = QPointF(aX + i, aY + j)

print(getArcBoundingRect(a, b, c))

Координаты aX, aY и тд. реальные. На проверке радиусов сразу выкидывает сообщение "radius1 != radius2". Может я где с кодом на косячил.
Записан
ibnz
Гость
« Ответ #27 : Декабрь 22, 2015, 11:32 »

В проверке радиусов hypot можно заменить на сравнение квадратов. Будет работать быстрее.
Глянь что там за радиусы получаются. Наверное допуск больший нужен.
Замени fuzzyCompare на abs(radius1 - radius2)<delta. И поиграйся с дельтой.
Или если уверен в корректности исходных данных вообще исключи проверку.
« Последнее редактирование: Декабрь 22, 2015, 11:37 от ibnz » Записан
popper
Гость
« Ответ #28 : Декабрь 22, 2015, 12:10 »

Мне эти данные нужны для того чтобы отрисовывать дуги в QGraphicsScene через drawArc(). Или может найдется более рациональное решение данной задачи?

Если результатом должна быть дуга на QGraphicsScene, то проще всего добавить на сцену  QGraphicsPathItem, в котором задать QPainterPath с инструкцией arcTo() внутри.

В любом случае, нужно вычислять startAngle и sweepLength (аналог spanAngle).  Для упрощения кода, вычисляющего углы, можно воспользоваться функционалом QLineF::angleTo, создав две линии из точек (A;C) и (B;C).
Записан
supertux
Гость
« Ответ #29 : Декабрь 22, 2015, 12:46 »

Изначально у меня были мысли про arcTo. Правда мне немного не понятно как оно рисует дуги.

Пример:

Код:
        path = QPainterPath()
        path.arcTo(50, 50, 150, 60, 180, 90)
        self.ui.graphicsView.scene.addPath(path)

Что получилось:

Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.049 секунд. Запросов: 22.