using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace AVC
{
/// <summary>
/// Обертка для недокументированной функции acedNEntSelPEx
/// </summary>
public static class ObjUnderPoint
{
static int ver = Application.Version.Major;
/// <summary>
/// Поиск видимого объекта чертежа под заданной точкой
/// Точку можно передать или запросить у пользователя
/// Возвращает только 1 объект (верхний в порядке DrawOrder)
/// Работает только с MdiActiveDocument и только на текущем Layout
/// </summary>
/// <param name="Prompt">Запрос выбора точки</param>
/// <param name="Picked">Точка для поиска в UCS (передаваемая методу или возвращаемая от пользователя)</param>
/// <param name="UsePickedPoint">Использовать переданную точку и ничего не запрашивать у пользователя</param>
/// <param name="Transform">Какая-то матрица. Может пересчет текущей системы координат в систему координат выбранного объекта?</param>
/// <param name="TransSpace">Видеть сквозь viewport</param>
/// <param name="GSMarker">Код SubEntity (Часть солида) Например 5-грань,6-вершина,26-ребро... 0-неделимый объект</param>
/// <returns>Список найденных объектов. Сначала видимый объект, потом блоки в который он включен, потом viewport (если включен TransSpace) </returns>
public static List<ObjectId> Find(string Prompt, out Point3d Picked, bool UsePickedPoint, out Matrix3d Transform, bool TransSpace, out int GSMarker)
{
List<ObjectId> ret = new List<ObjectId>();
long[] adsname = { 0, 0 };
IntPtr resbuf = IntPtr.Zero;
int result = 0;
uint transSpaceFlag = (uint)(TransSpace ? 1 : 0);
int pickflag = UsePickedPoint ? 1 : 0;
if (ver < 19) // AutoCAD 2012 и старее
{
if (IntPtr.Size == 4)
result = acedNEntSelPEx2012x32("", adsname, out Picked, pickflag, out Transform, out resbuf, transSpaceFlag, out GSMarker);
else
result = acedNEntSelPEx2012x64("", adsname, out Picked, pickflag, out Transform, out resbuf, transSpaceFlag, out GSMarker);
}
else // AutoCAD 2013 и новее
{
if (IntPtr.Size == 4)
result = acedNEntSelPEx2013x32("", adsname, out Picked, pickflag, out Transform, out resbuf, transSpaceFlag, out GSMarker);
else
result = acedNEntSelPEx2013x64("", adsname, out Picked, pickflag, out Transform, out resbuf, transSpaceFlag, out GSMarker);
}
if (result == 5100) // 5100 == OK
{
ObjectId id = new ObjectId();
switch (ver)
{
case 17: acdbGetObjectId17(ref id, adsname); break;
case 18: acdbGetObjectId18(ref id, adsname); break;
case 19: acdbGetObjectId19(ref id, adsname); break;
case 20: acdbGetObjectId20(ref id, adsname); break;
default: throw new NotImplementedException("Комманда не совместима с данной версией автокада");
}
if (!id.IsNull) ret.Add(id);
if (resbuf != IntPtr.Zero) // значит попался вьюпорт или блок
{
ResultBuffer buffer = (ResultBuffer)DisposableWrapper.Create(typeof(ResultBuffer), resbuf, true);
foreach (TypedValue v in buffer) // первым в списке будет самый глубоко вложенный блок, последним - вьюпорт
ret.Add((ObjectId)v.Value);
buffer.Dispose();
}
}
return ret;
}
/// <summary>
/// Поиск видимого объекта чертежа под заданной точкой. Видит "сквозь" вьюпорты
/// Возвращает только 1 объект (верхний в порядке DrawOrder)
/// Работает только с MdiActiveDocument и только на текущем листе (Layout). Система координат листа должна быть мировой.
/// </summary>
/// <param name="Picked">Точка поиска в UCS</param>
/// <returns>Список найденных объектов. Сначала видимый объект, потом блоки в который он включен, потом viewport (если включен TransSpace)</returns>
public static List<ObjectId> Find(Point3d Picked)
{
Matrix3d xform;
int gsmarker = 0;
// set uTransSpaceFlag to 0, if the current layout is in model space
bool transSpace = ((Convert.ToInt16(AcadApp.GetSystemVariable("CVPORT")) == 1)); // Paper space
return Find("", out Picked, true, out xform, transSpace, out gsmarker);
}
#region acdbGetObjectId
[DllImport("acdb17.dll", EntryPoint = "acdbGetObjectId", CallingConvention = CallingConvention.Cdecl)]
private static extern int acdbGetObjectId17(ref ObjectId objId, long[] name);
[DllImport("acdb18.dll", EntryPoint = "acdbGetObjectId", CallingConvention = CallingConvention.Cdecl)]
private static extern int acdbGetObjectId18(ref ObjectId objId, long[] name);
[DllImport("acdb19.dll", EntryPoint = "acdbGetObjectId", CallingConvention = CallingConvention.Cdecl)]
private static extern int acdbGetObjectId19(ref ObjectId objId, long[] name);
[DllImport("acdb20.dll", EntryPoint = "acdbGetObjectId", CallingConvention = CallingConvention.Cdecl)]
private static extern int acdbGetObjectId20(ref ObjectId objId, long[] name);
#endregion
#region acedNEntSelPEx
[DllImport("acad.exe", EntryPoint = "?acedNEntSelPEx@@YAHPB_WQAJQANHQAY03NPAPAUresbuf@@IPAH@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern int acedNEntSelPEx2012x32(string prompt, long[] adsname, out Point3d picked, int pickflag, out Matrix3d transform, out IntPtr resbuf, uint transSpaceFlag, out int gsMarker);
[DllImport("acad.exe", EntryPoint = "?acedNEntSelPEx@@YAHPEB_WQEA_JQEANHQEAY03NPEAPEAUresbuf@@IPEA_J@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern int acedNEntSelPEx2012x64(string prompt, long[] adsname, out Point3d picked, int pickflag, out Matrix3d transform, out IntPtr resbuf, uint transSpaceFlag, out int gsMarker);
[DllImport("accore.dll", EntryPoint = "?acedNEntSelPEx@@YAHPB_WQAJQANHQAY03NPAPAUresbuf@@IPAH@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern int acedNEntSelPEx2013x32(string prompt, long[] adsname, out Point3d picked, int pickflag, out Matrix3d transform, out IntPtr resbuf, uint transSpaceFlag, out int gsMarker);
[DllImport("accore.dll", EntryPoint = "?acedNEntSelPEx@@YAHPEB_WQEA_JQEANHQEAY03NPEAPEAUresbuf@@IPEA_J@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern int acedNEntSelPEx2013x64(string prompt, long[] adsname, out Point3d picked, int pickflag, out Matrix3d transform, out IntPtr resbuf, uint transSpaceFlag, out int gsMarker);
#endregion
}
}