Добрый день. Ребята, может быть, кто-то разбирается в API ObjectARX Autocad. Я новенький в этом направлении и не могу разобраться с ошибкой, связанной с использованием ручек для редактирования окружности. При использовании ручек должен изменяться радиус окружности, но сейчас почему-то происходит вылет приложения. Это связанно именно с функционалом ручек, так как другие команды работают корректно.
Если кто-то сталкивался с чем-то подобным или понимает, что тут не так, подскажите, пожалуйста. Код методов для ручек ниже:
P.S. Если я случайно нарушил какое-то из правил форума, напишите мне, пожалуйста.
Если кто-то сталкивался с чем-то подобным или понимает, что тут не так, подскажите, пожалуйста. Код методов для ручек ниже:
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. Если я случайно нарушил какое-то из правил форума, напишите мне, пожалуйста.