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

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 часа коту под хвост. Измучался с отладкой, пока проблему локализовывал. Нужно поспать чуток...
 
Последнее редактирование:

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 185
Реакции
10 844
Это известный баг, даже тут писали неоднократно. Зависимость isOnshape от масштаба связана с тем, что этот метод (предположительно) реализован через растрирование контура. Выход - временно увеличивать масштаб до упора или писать собственную реализацию.
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Зависимость isOnshape от масштаба связана с тем, что этот метод (предположительно) реализован через растрирование контура
Во как (2017 год)

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

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 185
Реакции
10 844
При указании любого положительного значения (1, 0.1, 0.0001) получаем всегда [cdrOutsideShape] на любых масштабах отображения
Это баг. Чувствительность должна работать
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Это баг. Чувствительность должна работать
Проверил ещё раз на тестовом примере из 1-го топика: чем меньше число HotArea (0.1 => 0.01 => 0.001 => 0.0001), тем сильнее себя проявляет сабжевый артефакт (тем сильнее нужно увеличить изображение, чтобы получить cdrInsideShape). Например, при значении 0.0001 метод IsOnShape корректно срабатывает (возвращает cdrInsideShape) только на двух последних/максимальных шагах увеличения.

И остаётся вопрос, как работает HotArea по умолчанию (при значении -1). Как в этом случае определяется порог чувствительности. Обеспечивается максимальная точность ?
 
Последнее редактирование:

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 185
Реакции
10 844
чем меньше число HotArea (0.1 => 0.01 => 0.001 => 0.0001), тем сильнее себя проявляет сабжевый артефакт (тем сильнее нужно увеличить изображение, чтобы получить cdrInsideShape).
Ну так логично же?
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Ну так логично же?
Где здесь логика ? Чем меньше число, тем выше точность (меньше погрешность/толерантность).
Почему в этом случае усиление проявления артефакта должно быть логичным ?
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 185
Реакции
10 844
Чем меньше число, тем выше точность (меньше погрешность/толерантность).
Почему в этом случае усиление проявления артефакта должно быть логичным ?
Данное число позиционируется как "горячая зона допуска"
Логично то, что чем меньше эта зона тем сложнее попасть в контур в областях близких к его границе
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Данное число позиционируется как "горячая зона допуска"
Логично то, что чем меньше эта зона тем сложнее попасть в контур в областях близких к его границе
Зачем нам попадать в область вблизи контура ? Нам нужно попасть в область внутри контура, а не вблизи его.
Соответственно, чем меньше этот допуск, тем должно быть проще попасть в область внутри контура (не задев при этом область вблизи контура).
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 185
Реакции
10 844
Я не пойму, вам, как обычно, чисто поговорить?
Хорошо, давайте потеоретизируем пока я тут. "Горячая зона" - это, так сказать, ширина пограничной полосы вдоль контура. Если он сильно маленький, соответственно, и попасть в него сложнее, не так ли?
Предположим у вас во дворе стоит деревенский сортир, одно очко которого, скажем, 40 сантиметров, а другое - 5
В которое из них будет попасть проще с высоты вашего полуроста?
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
"Горячая зона" - это, так сказать, ширина пограничной полосы вдоль контура. Если он сильно маленький, соответственно, и попасть в него сложнее, не так ли?
Ещё раз: нам не нужно попадать попадать в пограничную зону контура. Нам нужно попасть внутрь контура. Т.е. туда, что внутри контура. И если эта пограничная зона контура будет меньше, то и попасть ВНУТРЬ контура будет проще.

Предположим у вас во дворе стоит деревенский сортир, одно очко которого, скажем, 40 сантиметров, а другое - 5
В которое из них будет попасть проще с высоты вашего полуроста?
Воспитание...
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 185
Реакции
10 844
Ещё раз: нам не нужно попадать попадать в пограничную зону контура. Нам нужно попасть внутрь контура. Т.е. туда, что внутри контура. И если эта пограничная зона контура будет меньше, то и попасть ВНУТРЬ контура будет проще.
Не совсем так, то есть, совсем не так.
Это ширина "нейтральной зоны" т.е. зоны неопределенности, в которую попадают квадраты частично занятые объектом а частично фоном. Чем эта зона будет больше, тем попасть в нее проще. Наверное как то так.
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Это ширина "нейтральной зоны" т.е. зоны неопределенности, в которую попадают квадраты частично занятые объектом а частично фоном. Чем эта зона будет больше, тем попасть в нее проще.
Наверное, не "зона неопределённости", а внутренняя свободная область фигуры (внутри которой другие фигуры считаются cdrInsideShape). Если так, то эта самая область должна определяться не параметром функции, а фактической геометрией фигуры.
Если фигуру в 2 раза увеличить, то и внутренняя область по площади должна вдвое увеличиться. И никакие параметры функции не могут обратно уменьшить эту область (игнорируя фактические размеры фигуры). Иначе это уже лошади в вакууме получаются...
 

dastin

Некромант-любитель
12 лет на форуме
Сообщения
2 145
Реакции
2 043
Это ширина "нейтральной зоны" т.е. зоны неопределенности,
не ширина ... но её половина
HotArea
Double
Specifies the tolerance radius in which to evaluate the presence of the shape.
и, как мне кажется, указывая 0,1 стоит помнить в каких "попугаях" указано Unit - 0,1 pt и 0,1 мм братья безусловно, но только по маме.
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Финализируем сабж. Корректно работающий (не зависящий от масштаба отображения) 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 угловых точек и выполнить обратное вращение относительно той же общей точки. Я так делаю в своём проекте. Ну а при проверке вхождения текста я его предварительно скривляю (вернее, не его самого, а его дубликат) и только затем проверяю. Скривление нужно постольку, поскольку текстовый объект имеет размеры большие, чем визуально занимают линии текста. Только дублирование и скривление - достаточно тяжёлая операция и в разы замедляет работу кода.
 
Последнее редактирование: