[CDR X4 и ранее] Артефакт Shape.IsOnShape: результат зависит от масштаба отображения

  • Автор темы Автор темы Cyrax
  • Дата начала Дата начала

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Во вложении прикрепил файл Corel X3. Там в красном прямоугольнике расположен жёлтый прямоугольник. Задача: получить значение [IsOnShape = cdrInsideShape] для угловой точки жёлтого прямоугольника. Выделяем оба прямоугольника и запускаем вот этот код:
Код:
Sub testIsOnShape()
    Dim big As shape, small As shape
    If (ActiveSelectionRange.item(1).SizeWidth > ActiveSelectionRange.item(2).SizeWidth) Then
        Set big = ActiveSelectionRange.item(1)
        Set small = ActiveSelectionRange.item(2)
    Else
        Set big = ActiveSelectionRange.item(2)
        Set small = ActiveSelectionRange.item(1)
    End If

    MsgBox "Влезает ли [small] в [big]: " & vbCrLf & (big.IsOnShape(small.LeftX + small.SizeWidth, small.BottomY) = cdrPositionOfPointOverShape.cdrInsideShape)
End Sub


Результат: на больших масштабах отображения получаем значение [cdrInsideShape], на малых [cdrOutsideShape]
Возможно, это зависит от 3-го параметра HotArea:
1) При его отсутствии (используется значение по умолчанию) наблюдается описанная картина
2) При указании любого положительного значения (1, 0.1, 0.0001) получаем всегда [cdrOutsideShape] на любых масштабах отображения

В общем, нужно сделать так, чтобы на любых масштабах IsOnShape возвращал [cdrInsideShape]
4 часа коту под хвост. Измучался с отладкой, пока проблему локализовывал. Нужно поспать чуток...
 
Последнее редактирование:
Это известный баг, даже тут писали неоднократно. Зависимость isOnshape от масштаба связана с тем, что этот метод (предположительно) реализован через растрирование контура. Выход - временно увеличивать масштаб до упора или писать собственную реализацию.
 
Зависимость isOnshape от масштаба связана с тем, что этот метод (предположительно) реализован через растрирование контура
Во как (2017 год)

А 3-й параметр на что-нибудь влияет ? Кроме как:
1) При его отсутствии (используется значение по умолчанию) наблюдается описанная картина
2) При указании любого положительного значения (1, 0.1, 0.0001) получаем всегда [cdrOutsideShape] на любых масштабах отображения
 
При указании любого положительного значения (1, 0.1, 0.0001) получаем всегда [cdrOutsideShape] на любых масштабах отображения
Это баг. Чувствительность должна работать
 
Это баг. Чувствительность должна работать
Проверил ещё раз на тестовом примере из 1-го топика: чем меньше число HotArea (0.1 => 0.01 => 0.001 => 0.0001), тем сильнее себя проявляет сабжевый артефакт (тем сильнее нужно увеличить изображение, чтобы получить cdrInsideShape). Например, при значении 0.0001 метод IsOnShape корректно срабатывает (возвращает cdrInsideShape) только на двух последних/максимальных шагах увеличения.

И остаётся вопрос, как работает HotArea по умолчанию (при значении -1). Как в этом случае определяется порог чувствительности. Обеспечивается максимальная точность ?
 
Последнее редактирование:
чем меньше число HotArea (0.1 => 0.01 => 0.001 => 0.0001), тем сильнее себя проявляет сабжевый артефакт (тем сильнее нужно увеличить изображение, чтобы получить cdrInsideShape).
Ну так логично же?
 
Ну так логично же?
Где здесь логика ? Чем меньше число, тем выше точность (меньше погрешность/толерантность).
Почему в этом случае усиление проявления артефакта должно быть логичным ?
 
Чем меньше число, тем выше точность (меньше погрешность/толерантность).
Почему в этом случае усиление проявления артефакта должно быть логичным ?
Данное число позиционируется как "горячая зона допуска"
Логично то, что чем меньше эта зона тем сложнее попасть в контур в областях близких к его границе
 
Данное число позиционируется как "горячая зона допуска"
Логично то, что чем меньше эта зона тем сложнее попасть в контур в областях близких к его границе
Зачем нам попадать в область вблизи контура ? Нам нужно попасть в область внутри контура, а не вблизи его.
Соответственно, чем меньше этот допуск, тем должно быть проще попасть в область внутри контура (не задев при этом область вблизи контура).
 
Я не пойму, вам, как обычно, чисто поговорить?
Хорошо, давайте потеоретизируем пока я тут. "Горячая зона" - это, так сказать, ширина пограничной полосы вдоль контура. Если он сильно маленький, соответственно, и попасть в него сложнее, не так ли?
Предположим у вас во дворе стоит деревенский сортир, одно очко которого, скажем, 40 сантиметров, а другое - 5
В которое из них будет попасть проще с высоты вашего полуроста?
 
"Горячая зона" - это, так сказать, ширина пограничной полосы вдоль контура. Если он сильно маленький, соответственно, и попасть в него сложнее, не так ли?
Ещё раз: нам не нужно попадать попадать в пограничную зону контура. Нам нужно попасть внутрь контура. Т.е. туда, что внутри контура. И если эта пограничная зона контура будет меньше, то и попасть ВНУТРЬ контура будет проще.

Предположим у вас во дворе стоит деревенский сортир, одно очко которого, скажем, 40 сантиметров, а другое - 5
В которое из них будет попасть проще с высоты вашего полуроста?
Воспитание...
 
Ещё раз: нам не нужно попадать попадать в пограничную зону контура. Нам нужно попасть внутрь контура. Т.е. туда, что внутри контура. И если эта пограничная зона контура будет меньше, то и попасть ВНУТРЬ контура будет проще.
Не совсем так, то есть, совсем не так.
Это ширина "нейтральной зоны" т.е. зоны неопределенности, в которую попадают квадраты частично занятые объектом а частично фоном. Чем эта зона будет больше, тем попасть в нее проще. Наверное как то так.
 
Это ширина "нейтральной зоны" т.е. зоны неопределенности, в которую попадают квадраты частично занятые объектом а частично фоном. Чем эта зона будет больше, тем попасть в нее проще.
Наверное, не "зона неопределённости", а внутренняя свободная область фигуры (внутри которой другие фигуры считаются cdrInsideShape). Если так, то эта самая область должна определяться не параметром функции, а фактической геометрией фигуры.
Если фигуру в 2 раза увеличить, то и внутренняя область по площади должна вдвое увеличиться. И никакие параметры функции не могут обратно уменьшить эту область (игнорируя фактические размеры фигуры). Иначе это уже лошади в вакууме получаются...
 
Это ширина "нейтральной зоны" т.е. зоны неопределенности,
не ширина ... но её половина
HotArea
Double
Specifies the tolerance radius in which to evaluate the presence of the shape.
и, как мне кажется, указывая 0,1 стоит помнить в каких "попугаях" указано Unit - 0,1 pt и 0,1 мм братья безусловно, но только по маме.
 
Финализируем сабж. Корректно работающий (не зависящий от масштаба отображения) IsOnShape:
Код:
Function IsOnShape(shape As shape, ByVal X As Double, ByVal Y As Double, Optional ByVal HotArea As Double = -1) As cdrPositionOfPointOverShape

   Dim settPs As Boolean: settPs = Application.ActiveDocument.PreserveSelection: Application.ActiveDocument.PreserveSelection = False
   Dim settEe As Boolean: settEe = Application.EventsEnabled: Application.EventsEnabled = False
   Dim settOp As Boolean: settOp = Application.Optimization: Application.Optimization = True
   
    Dim view As ActiveView: Set view = Application.ActiveWindow.ActiveView
    Dim viewX As Double, viewY As Double, viewW As Double, viewH As Double: view.GetViewArea viewX, viewY, viewW, viewH
    view.zoom = 1000000  'в Corel X3 максимум 405651
   
    IsOnShape = shape.IsOnShape(X, Y, HotArea)
    view.SetViewArea viewX, viewY, viewW, viewH
   
   Application.ActiveDocument.PreserveSelection = settPs
   Application.EventsEnabled = settEe
   Application.Optimization = settOp
End Function

Если проверка выполняется часто, то лучше масштабирование и восстановление масштаба вынести в начало/конец макроса.

P.S. В одной из тем писали, что для проверки вхождения прямоугольных объектов и текста достаточно проверить 4 угловые точки (в большинстве случаев да, достаточно проверить 4 угловые точки). И что при наличии поворота "так уже не получится". На самом деле при наклоне прямоугольных объектов или текста "так" тоже получится. Достаточно выполнить вращение (относительно общей точки) главного объекта и проверяемого объекта на угол поворота проверяемого объекта со знаком "минус", выполнить проверку 4 угловых точек и выполнить обратное вращение относительно той же общей точки. Я так делаю в своём проекте. Ну а при проверке вхождения текста я его предварительно скривляю (вернее, не его самого, а его дубликат) и только затем проверяю. Скривление нужно постольку, поскольку текстовый объект имеет размеры большие, чем визуально занимают линии текста. Только дублирование и скривление - достаточно тяжёлая операция и в разы замедляет работу кода.
 
Последнее редактирование: