ADN Club > AutoCAD .NET API

Анализ пересечения объектов

(1/2) > >>

Николай Коломоец:
Доброго всем времени суток.

Есть задача - проанализировать, находится ли точка на блоке (на каком-либо из его примитивов, за исключением текста или атрибута, штриховки).
Написал такой текст:


--- Код - C# [Выбрать] ---private int Compare(Point3d point, BlockReference br, double radius)        {            Database db = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database;            Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;            bool intersect = false;            using (Transaction trans = db.TransactionManager.StartTransaction())            {                BlockTableRecord btr = trans.GetObject(br.BlockTableRecord,OpenMode.ForRead) as BlockTableRecord;                //BlockTableRecord modelBTR = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;                Matrix3d brTransformedCoord = br.BlockTransform;                 foreach (ObjectId objId in btr)                {                    DBObject obj = trans.GetObject(objId, OpenMode.ForWrite);                    if ((obj is Entity) && (!(obj is DBText)) && (!(obj is MText)) && (!(obj is Hatch)) && (!(obj is Spline)))                    {                        Entity ent = (Entity)obj;                        Entity tempEnt = ent;                        tempEnt.TransformBy(brTransformedCoord);                        Point3dCollection pts = new Point3dCollection();                        //Plane pl = new Plane();                        Circle pointCircle = new Circle(point, new Vector3d(0, 0, 1), radius);                        //modelBTR.AppendEntity(pointCircle);                        //trans.AddNewlyCreatedDBObject(pointCircle, true);                        try                        {                            tempEnt.IntersectWith(pointCircle, Intersect.OnBothOperands, pts, IntPtr.Zero, IntPtr.Zero);                        }                        catch (Autodesk.AutoCAD.Runtime.Exception ex)                        {                        //    MessageBox.Show(ex.Message + ex.Source + "\n");                        }                        if (pts.Count > 0)                            intersect = true;                        //pointCircle.Erase();                    }                }                trans.Commit();            }            if (intersect == true)                return 0;                        return -1;        }
Тут point - точка; br - вставка блока: функция должна вернуть 0, если точка находится на блоке; radius - "допуск", тут используется для прорисовки малого круга: считаю, что точка находится на блоке, если круг радиуса radius с центром в точке point пересекает какой-либо из примитивов блока.

В общем, данная функция никогда не возвращает 0 в реальной жизни. Как мне кажется, я неправильно понимаю работу метода IntersectWith.

Анализировать отдельно каждый тип примитива (линию, дугу и т.п.) тоже наверное неправильно. Как правильнее всего поступить в данной ситуации?

Алексей Кулик:
В порядке предположения: а система координат вхождения блока мировая? Угол поворота 0? Масштабы по разным осям тоже равны 1?

Николай Коломоец:
Система координат мировая. Масштабы все по 1, хотя тут хотелось бы узнать, что делать, если будет не так - программа все-таки должна работать при любых блоках. А вот насчет поворота - тут интереснее: блоки в большинстве своем динамические. Угол вставки самого блока почти всегда 0, но динамический параметр - угол поворота! Вообще, блоки могут быть любые, в т.ч. динамические, параметрические.
Выходит, что Entity.TransformBy(BlockReference.BlockTransform) не учитывает все эти параметры?

P.S. Пока, чтобы работало, сделал анализ пересечения с конкретным типом данных примитива из br.BlockTableRecord - Circle, Arc, Curve и Polyline. Работает "почти" нормально, но это явно неверный способ решения проблемы.

Алексей Кулик:
Могу попытаться помочь только с общим алгоритмом, но никак не с реализацией :(
Что бы сделал я:

* Перевести координаты точки / примитива "в блок" - т.е. сложить координаты (предварительно умножив на коэффициенты масштабов по соответствующим осям), высчитать полярное смещение и т.п.
* Пройтись по всем подпримитивам описания блока и проверить для каждого IntersectWithКак-то так, наверное...
P.S. На caduser.ru, кажется, были варианты лисповых решений поиска пересечения примитивов и блоков, но я особо за ними не следил, поскольку не требовалось решать подобные задачи.

Александр Ривилис:
Для примитивов унаследованных от Curve я вообще не вижу смысла так усложнять код. Достаточно проверять расстояние от точки до примитива при помощи метода GetClosestPointTo. С остальными типами примитивов придётся разбираться отдельно. Для Region и Solid3d потребуется использовать BREP .NET API.

Навигация

[0] Главная страница сообщений

[#] Следующая страница

Перейти к полной версии