Как использовать IRelationalOperator2 и GeometryBag

9

Я хочу использовать метод IsNear IRelationalOperator2. В документации говорится, что GeometryBag поддерживает интерфейс IRelationalOperator2. Но это просто не работает и приводит к исключению "... невозможно преобразовать COM-объект ... Такой интерфейс не поддерживается ..."

IRelationalOperator2 relationalOperator = (IRelationalOperator2)geometry;

Тот же код отлично работает с IRelationalOperator, но метод IsNear отсутствует:

IRelationalOperator relationalOperator = (IRelationalOperator)geometry;

Что не так - код, документация или это баг? «geometry» - это геометрия типа esriGeometryBag и содержит несколько полилиний. Я использовал прямое приведение, чтобы получить исключение .NET.

Георг Хефеле
источник
Я забыл сказать, что я использую 10.0 SP2
Георг Хефеле
1
Эта проблема все еще существует в ArcGis 10.1 (а также в ArcGis 10.0 SP 5). К сожалению, до сих пор никто не отправлял эту ошибку в ESRI, поэтому я сообщил местному дистрибьютору, и ESRI зарегистрировала ошибку сейчас. Я надеюсь, что это будет исправлено с помощью следующего пакета обновления.
дпалметц

Ответы:

6

Здесь определенно что-то подозрительное происходит с 10.0 sp2.

Я могу привести геометрическую сумку к IRelationalOperator2, в противном случае этот тест скажет «невозможно привести», плюс я получу исключение нулевой ссылки.

Однако при первом звонке в IsNear я получаю исключение.

System.InvalidCastException occurred
  Message=Unable to cast COM object of type 'ESRI.ArcGIS.Geometry.GeometryBagClass' to interface type 'ESRI.ArcGIS.Geometry.IRelationalOperator2'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{839F5C7E-ED5F-4B3F-8F97-C0A9CC4817EE}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
  Source=ESRI.ArcGIS.Geometry

Вот тест:

private void GBTest(IPoint pnt)
{
    // this line does not fail
    var relop = new GeometryBagClass() as IRelationalOperator2;

    if (relop == null)
        Debug.Print("unable to cast"); // this doesn't print out

    var coll = relop as IGeometryCollection;
    coll.AddGeometry(pnt);
    //((ISpatialIndex)coll).AllowIndexing = true;
    //((ISpatialIndex)coll).Invalidate();

    var pnt2 = ((IClone)pnt).Clone() as IPoint;
    ((ITransform2D)pnt2).Move(100.0, 100.0);
    if (relop.IsNear(pnt2, 1000.0)) // exception here
        Debug.Print("test 1 fail");

    if (!relop.IsNear(pnt2, 10.0))
        Debug.Print("test 2 fail");
}

Вот еще один тест. Обратите внимание, как я могу привести без исключения, но получить исключение InvalidCast при вызове IsNear.

private void GBTest(IPoint pnt)
{
    var coll = new GeometryBagClass();
    ((IGeometry)coll).SpatialReference = pnt.SpatialReference;

    coll.AddGeometry(pnt);
    coll.GeometriesChanged();

    var relop = (IRelationalOperator2)coll; // would expect the exception here

    var pnt2 = ((IClone)pnt).Clone() as IPoint;
    ((ITransform2D)pnt2).Move(100.0, 100.0);
    if (relop.IsNear(pnt2, 1000.0)) // exception here
        Debug.Print("test 1 fail");

    if (!relop.IsNear(pnt2, 10.0))
        Debug.Print("test 2 fail");
}
Кирк Куйкендалл
источник
Кирк, я сделал то же самое. Ваш тест никогда не будет верным, потому что в это время значение «relop» имеет значение {ESRI.ArcGIS.Geometry.GeometryBagClass} со счетчиком 0. «Null» или исключение происходит, если вы пытаетесь привести реальный GeometryBag (включает данные).
Георг Хефеле
@ Георг Я добавил код, показывающий, как я могу привести непустой геометрический класс к IRelationalOperator2. Для меня загадкой является то, что исключение InvalidCast не выдается, когда я фактически выполняю приведение - только при вызове IsNear.
Кирк Куйкендалл
Кирк, спасибо тебе за код и твои комментарии. Я могу воспроизвести Ваши результаты. Одна странная вещь: после фактического приведения и перед вызовом IsNear локальные объекты в Visual Studio показывают некоторые проблемы для «relop» - все IGeometry5-Entries имеют значение «((ESRI.ArcGIS.Geometry.GeometryBagClass) (relop)). IGeometry5_xxxx). 'сгенерировал исключение типа' System.Invalid.CastException '. Но на самом деле исключение не выдается. Это происходит при вызове IsNear.
Георг Хэфеле
Я также испытал странное поведение приведения в 10 (не уверен, были ли установлены какие-либо SP), на этот раз с классом VariantStreamIO. Я постараюсь выделить и воспроизвести проблему. Если это ошибка, то она действительно серьезная.
Петр Кребс
0

Я полагаю, что это ошибка в документации, поскольку GeometryBag - это набор точек / линий / многоугольников. Выполнение некоторых операций ITopologicalOperator в смешанной и согласованной коллекции геометрических типов может быть невозможным. Если бы вы использовали IGeometryCollection полилиний, хотя я думаю, что ваше решение будет работать.

Стив
источник