• XSS.stack #1 – первый литературный журнал от юзеров форума

ObjectARX

Maxwell

CD-диск
Пользователь
Регистрация
11.05.2025
Сообщения
16
Реакции
0
Добрый день. Ребята, может быть, кто-то разбирается в API ObjectARX Autocad. Я новенький в этом направлении и не могу разобраться с ошибкой, связанной с использованием ручек для редактирования окружности. При использовании ручек должен изменяться радиус окружности, но сейчас почему-то происходит вылет приложения. Это связанно именно с функционалом ручек, так как другие команды работают корректно.
Если кто-то сталкивался с чем-то подобным или понимает, что тут не так, подскажите, пожалуйста. Код методов для ручек ниже:

C++:
Acad::ErrorStatus AcDbDoubleCircle::subGetGripPoints(
    AcGePoint3dArray& gripPoints,
    AcDbIntArray& osnapModes,
    AcDbIntArray& geomIds) const
{
    assertReadEnabled();

    gripPoints.setLogicalLength(0);
    osnapModes.setLogicalLength(0);
    geomIds.setLogicalLength(0);

    // Безопасное вычисление базисных векторов
    AcGeVector3d xAxis, yAxis;
    if (m_normal.isZeroLength()) {
        xAxis = AcGeVector3d::kXAxis;
        yAxis = AcGeVector3d::kYAxis;
    }
    else {
        xAxis = m_normal.perpVector();
        if (xAxis.isZeroLength()) {
           
            xAxis = AcGeVector3d::kXAxis - m_normal * m_normal.x;
            if (xAxis.isZeroLength()) {
                xAxis = AcGeVector3d::kYAxis - m_normal * m_normal.y;
            }
        }
        xAxis.normalize();
        yAxis = m_normal.crossProduct(xAxis).normalize();
    }

    for (int circleIdx = 0; circleIdx < 2; ++circleIdx) {
        // Пропускаем круги с нулевым радиусом
        if (m_circleRadii[circleIdx] <= 1e-6) continue;

        const AcGePoint3d& center = m_circleCenters[circleIdx];

        // Центральная точка (индекс circleIdx*5)
        gripPoints.append(center);
        osnapModes.append(3); // Замена kAcOsnapCenter на 3 (режим привязки "Центр")
        geomIds.append(circleIdx * 5);

        //  4 радиальные точки под углами 45°, 135°, 225°, 315° (индексы circleIdx*5+1..circleIdx*5+4)
        for (int j = 0; j < 4; ++j) {
            double angle = M_PI / 4 + j * M_PI / 2; // 45°, 135°, 225°, 315°
            AcGeVector3d radial = xAxis * cos(angle) + yAxis * sin(angle);
            gripPoints.append(center + radial * m_circleRadii[circleIdx]);
            osnapModes.append(10); // Замена kAcOsnapNear на 10 (режим привязки "Ближайшая")
            geomIds.append(circleIdx * 5 + j + 1);
        }
    }

    return Acad::eOk;
}


// Растягивание
Acad::ErrorStatus AcDbDoubleCircle::subGetStretchPoints(AcGePoint3dArray& points) const
{
 
    AcDbIntArray osnapModes;  // Пустой массив для osnapModes (не обязателен для растягивания)
    AcDbIntArray geomIds;     // Пустой массив для geomIds (не обязателен для растягивания)
    subGetGripPoints(points, osnapModes, geomIds);  // Делегируем вызов subGetGripPoints



    return Acad::eOk;  // Возвращаем успешное выполнение вместо eNotImplementedYet
}



Acad::ErrorStatus AcDbDoubleCircle::subMoveStretchPointsAt(
    const AcDbIntArray& indices,
    const AcGeVector3d& offset)
{
    if (indices.isEmpty() || offset.isZeroLength())
        return Acad::eOk;

    assertWriteEnabled();
    bool bModified = false;

    // Безопасное вычисление базисных векторов
    AcGeVector3d xAxis, yAxis;
    if (m_normal.isZeroLength()) {
        xAxis = AcGeVector3d::kXAxis;
        yAxis = AcGeVector3d::kYAxis;
    }
    else {
        xAxis = m_normal.perpVector();
        if (xAxis.isZeroLength()) {
            xAxis = AcGeVector3d::kXAxis - m_normal * m_normal.x;
            if (xAxis.isZeroLength()) {
                xAxis = AcGeVector3d::kYAxis - m_normal * m_normal.y;
            }
        }
        xAxis.normalize();
        yAxis = m_normal.crossProduct(xAxis).normalize();
    }

    // Сохраняем старые центры для большой окружности
    AcGePoint3d oldCenter0 = m_circleCenters[0];

    for (int idx : indices) {
        int circleIndex = idx / 5;  // 0 или 1
        int gripType = idx % 5;     // 0 - центр, 1-4 - радиальные точки

        if (circleIndex < 0 || circleIndex > 1) continue;
        if (m_circleRadii[circleIndex] <= 1e-6) continue;

        if (gripType == 0) {
            // Перемещение центра
            m_circleCenters[circleIndex] += offset;
            bModified = true;
        }
        else {
            // Изменение радиуса
            double angle = M_PI / 4 + (gripType - 1) * M_PI / 2;
            AcGeVector3d radial = xAxis * cos(angle) + yAxis * sin(angle);

            // Новая позиция точки на окружности
            AcGePoint3d newPt = m_circleCenters[circleIndex] + radial * m_circleRadii[circleIndex] + offset;

            // Новый радиус - расстояние от центра до новой точки
            double newRadius = m_circleCenters[circleIndex].distanceTo(newPt);

            if (newRadius > 1e-6) {
                m_circleRadii[circleIndex] = newRadius;
                bModified = true;
            }
        }
    }

    // Если изменена большая окружность (index 0), обновляем центры кресткругов
    if (bModified && m_crossCircleIds.length() == 2)
    {
        bool bigCircleModified = false;
        for (int idx : indices) {
            if (idx / 5 == 0) { // Изменена большая окружность
                bigCircleModified = true;
                break;
            }
        }

        if (bigCircleModified) {
            AcDbCrossCircle* pCircle1 = nullptr;
            AcDbCrossCircle* pCircle2 = nullptr;
            if (acdbOpenObject(pCircle1, m_crossCircleIds[0], AcDb::kForWrite) == Acad::eOk &&
                acdbOpenObject(pCircle2, m_crossCircleIds[1], AcDb::kForWrite) == Acad::eOk)
            {
                AcGePoint3d c1 = pCircle1->center();
                AcGePoint3d c2 = pCircle2->center();
                double r1 = pCircle1->radius(); // Сохраняем радиус
                double r2 = pCircle2->radius(); // Сохраняем радиус
                double rBig = m_circleRadii[0];

                // Перемещаем центры кресткругов
                AcGeVector3d dirToC1 = (c1 - oldCenter0);
                double distC1 = dirToC1.length();
                if (distC1 > 1e-6) {
                    dirToC1.normalize();
                    AcGePoint3d newC1 = m_circleCenters[0] + dirToC1 * (rBig - r1);
                    pCircle1->setCenter(newC1);
                    pCircle1->markModified();
                }

                AcGeVector3d dirToC2 = (c2 - oldCenter0);
                double distC2 = dirToC2.length();
                if (distC2 > 1e-6) {
                    dirToC2.normalize();
                    AcGePoint3d newC2 = m_circleCenters[0] + dirToC2 * (rBig - r2);
                    pCircle2->setCenter(newC2);
                    pCircle2->markModified();
                }

                pCircle1->close();
                pCircle2->close();
            }
        }
    }

    if (bModified) {
        computeTangentCircles();
        updateGeometry();
        recordGraphicsModified(true);
    }

    return Acad::eOk;
}


P.S. Если я случайно нарушил какое-то из правил форума, напишите мне, пожалуйста.
 
Работал с этим апи когда-то, я так понимаю код написан нейронкой. Лучше сам открывай док и читай что и как
Но там с этим не просто, в мое время был достаточно кривой.
 
Работал с этим апи когда-то, я так понимаю код написан нейронкой. Лучше сам открывай док и читай что и как
Но там с этим не просто, в мое время был достаточно кривой.
Я до этого реализовывал аналогичную задачу по инструкции, сейчас с нейросетью попытался. Просто с той реализацией также ничего не выходило. Можете подсказать, почему программа моежт ломаться? Обычно такое бывает, когда забываешь удалить выделенную динимаческую память, но в моей реализации такого нет.
 
Привет! Была у меня такая же заморочка. Делал ручки для круга, вроде всё нормально, но как только начинаешь тянуть — бац, автокад падает. Долго мучался, пока не понял, что дело в обработке ручек при растягивании.
У тебя, как я понял, на каждый круг идёт 5 точек — одна в центре и четыре по радиусу. И вот тут важно: когда двигаешь ручку, надо точно понимать, за какую именно потянули.
Если это центр — просто смещаешь его. Если это одна из крайних — значит, тебе надо менять радиус, а не просто точку двигать.
Я у себя сделал просто: беру индекс ручки, делю на 5 — так узнаю, к какому кругу она относится. А остаток от деления подсказывает, что это за точка — центр или край.
С тех пор всё стало работать как часы, ничего не вылетает.
 
Привет! Была у меня такая же заморочка. Делал ручки для круга, вроде всё нормально, но как только начинаешь тянуть — бац, автокад падает. Долго мучался, пока не понял, что дело в обработке ручек при растягивании.
У тебя, как я понял, на каждый круг идёт 5 точек — одна в центре и четыре по радиусу. И вот тут важно: когда двигаешь ручку, надо точно понимать, за какую именно потянули.
Если это центр — просто смещаешь его. Если это одна из крайних — значит, тебе надо менять радиус, а не просто точку двигать.
Я у себя сделал просто: беру индекс ручки, делю на 5 — так узнаю, к какому кругу она относится. А остаток от деления подсказывает, что это за точка — центр или край.
С тех пор всё стало работать как часы, ничего не вылетает.
Большое спасибо Вам
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх