API7 - работа с динамическими массивами

Автор p3452, 21.12.20, 14:07:08

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

p3452

Коллеги, поделитесь опытом, кто как работает с массивами SAFEARRAY под API7?

Допустим не примере свойства IFeature7.ResultBodies:
ЦитироватьСвойство позволяет получить массив SAFEARRAY всех тел, входящих в дерево. Если возвращается один объект, то тип VARIANT-а будет VT_DISPATCH, если возвращается не­сколько объектов, то тип VARIANT-а будет VT_ARRAY | VT_DISPATCH.
Мой код во вложении, как это можно сделать по другому?
/// <summary> ТЕЛА дерева построения </summary>
/// <param name="_f"> IFeature7</param>
/// <returns>string</returns> Строка с перечнем описания Тел
internal static string testBody(IFeature7 _f)
{
string st = "";       
    if (_f == null) return "_f == null";

    try
    {
    Object[] arrBody = (Object[])_f.ResultBodies;
    if (arrBody != null)
    {
    IBody7 curBodi = null;    // текущее тело
           
    //+ перебираем ТЕЛА дерева
            for(int n=0; n<arrBody.Rank; n++)
{
for(int i=arrBody.GetLowerBound(n); i<=arrBody.GetUpperBound(n); i++)
{
st = st+ "n = "+ n.ToString()+ "   i = "+ i.ToString();
//+ получаем текущее Тело
                curBodi = (IBody7)arrBody[i];
                if (curBodi == null)
                {
                st = st+ "curBodi == null\n";
                break;
                }  
                st = st+ "    Наименование = ["+ curBodi.Name+ "]\n";  // Наименование тела
                st = st+ "Объект спецификации - "+ (curBodi.CreateSpcObjects ? "Да" : "Нет")+ "\n";              
}
}
    }
    else
    st =  "arrBodi == null";
    } catch //(Exception)
    {
    IBody7 bodi = (IBody7)_f.ResultBodies;
    if (bodi != null)
    st = "Наименование = ["+ bodi.Name+ "]\n";  // Наименование тела
else           
    st =  "bodi == null";
    }
    return st;
}
testBody.png

Вират Лакх

Пример на выделенных объектах чертежа, если нужно их перебрать (python):
sObjects = API7.IKompasDocument2D1(iKompasDocument2D).SelectionManager.SelectedObjects
if sObjects:
for sObject in sObjects if isinstance(sObjects, tuple) else (sObjects,):
otype = API7.IKompasAPIObject(sObject).Type
Если тип пришел не кортеж, а один элемент в виде его интерфейса, то превращаем его в кортеж с одним элементом.

p3452

Цитата: Вират Лакх от 22.12.20, 04:35:45Если тип пришел не кортеж, а один элемент в виде его интерфейса, то превращаем его в кортеж с одним элементом.

Если заменить модуль try...catch на
if (_f.ResultBodies.GetType().IsArray)
{
 ...
}
else
{
 ...
}
то код будет аналогичен Python-овскому...

Может, все-таки, есть другие варианты кода???

Вират Лакх

Цитата: p3452 от 22.12.20, 10:14:43то код будет аналогичен Python-овскому...
Может, все-таки, есть другие варианты кода???
Ваш код выше не аналогичен питоновскому. У меня одно тело цикла, а у вас два раза писать приходится одно и то же. Или функцию писать, которую надо вставить после if и после else. Вы же хотите от этого избавиться? Я перевожу интерфейс в кортеж из одного элемента, и цикл получает всегда последовательность.

p3452

Код аналогичен..., с учетом особенностей языка С# - собственно, целю вопроса и было - увидеть другие варианты кода на языке C#!
О достоинствах и недостатках Python спорить не будем - выбор давно уже сделан и, как понимаете, не в пользу Python.

Итак:
- Если кто-то знает другие варианты работы с динамическими массивами, под API7 Компаса на языке C#, поделитесь!

VirRus77

Займёмся некрофилией постов.
Вот расширение:
/// <summary>
/// Расширение для <see cref="IFeature7"/>.
/// </summary>
// ReSharper disable once InconsistentNaming
public static class IFeature7Extensions
{
    /// <summary>
    /// Объекты, входящие в состав данного объекта (грани, ребра, вершины).
    /// </summary>
    /// <param name="feature7">Интерфейс объекта Дерева построения.</param>
    /// <param name="type">Типы объектов документа-модели; соответствие интерфейсов API 5 и API 7.</param>
    /// <returns>Массив.</returns>
    public static Array ModelObjects(this IFeature7 feature7, ksObj3dTypeEnum type)
    {
        return (Array)feature7.ModelObjects[(int)type];
    }

    /// <summary>
    /// Объекты, входящие в состав данного объекта (грани, ребра, вершины).
    /// </summary>
    /// <param name="feature7">Интерфейс объекта Дерева построения.</param>
    /// <param name="type">Типы объектов документа-модели; соответствие интерфейсов API 5 и API 7.</param>
    /// <returns>Массив T.</returns>
    public static T[] ModelObjects<T>(this IFeature7 feature7, ksObj3dTypeEnum type)
    {
        return feature7.ModelObjects(type)
            .Cast<T>()
            .ToArray();
    }

    /// <summary>
    /// Получить массив тел.
    /// </summary>
    /// <param name="feature7">Интерфейс объекта Дерева построения.</param>
    /// <returns>Массив тел.</returns>
    public static IBody7[] ResultBodies(this IFeature7 feature7)
    {
        var bodiesObject = feature7.ResultBodies;

        if (bodiesObject == null)
        {
            return Array.Empty<IBody7>();
        }

        if(bodiesObject is Array array)
        {
            return array
                .Cast<IBody7>()
                .ToArray();
        }

        return new[] { (IBody7)bodiesObject };
    }
}
Как использовать:
var bodies = topFeature.ResultBodies();
var singleBody = bodies.Single();
+ Благодарностей: 3

p3452

А вот к ЭТОМУ стоило вернутся!
(Старая схема работает отлично, но, почему бы не перейти и на новую..., учитывая НОВЫЕ возможности C# и NET)
Надо будет опробовать...
+ Благодарностей: 1

zaytsev

#7
на основе данной темы вот так сделал С#
       
//получить массив из данных неизвестного типа
        public static Array GetArrObject(object inObjects)
        {
            if (inObjects == null)               
                return Array.Empty<object>();   //если пусто отдать пустой массив
            if (inObjects is Array array)
                return (Array)inObjects;        //если массив - отдать его
            else
                return new[] { inObjects };     //если одно значение -> в массив его и отдать
        }



        private void button4_Click(object sender, EventArgs e)
        {
//-------------------------------------------------------------------------------------------------------
            KompasObject kompas_5api = (KompasObject)Marshal.GetActiveObject("KOMPAS.Application.5");
            ksDocument3D Document3D = (ksDocument3D)kompas_5api.ActiveDocument3D();
            ksSelectionMng iSelectionManager = (ksSelectionMng)Document3D.GetSelectionMng();
            double area = 0;
            for (int i = 0; i < iSelectionManager.GetCount(); i++)
            {
                ksEntity iEntity = (ksEntity)iSelectionManager.GetObjectByIndex(i);
                if (iEntity.type == (int)Kompas6Constants3D.ksObj3dTypeEnum.o3d_face)    //если это плоскость
                {
                    ksFaceDefinition FaceDefinition = (ksFaceDefinition)iEntity.GetDefinition();
                    area += FaceDefinition.GetArea(0x1);
                }
            }
            MessageBox.Show(area.ToString(), "Площадь выделенных граней API5");

//-------------------------------------------------------------------------------------------------------
            IApplication app = (IApplication)Marshal.GetActiveObject("KOMPAS.Application.7");
            IKompasDocument document = app.ActiveDocument;
            IKompasDocument3D kompasDocument3D = (IKompasDocument3D)app.ActiveDocument;
            ISelectionManager iselectionManager = (ISelectionManager)kompasDocument3D.SelectionManager;
            area = 0;
            foreach (IModelObject item in GetArrObject(iselectionManager.SelectedObjects))
            {
                if (item.ModelObjectType == Kompas6Constants3D.ksObj3dTypeEnum.o3d_face)    //если это плоскость
                {
                    IFace face = (IFace)item;
                    area += face.GetArea(Kompas6Constants.ksLengthUnitsEnum.ksLUnMM);

                }
           }
            MessageBox.Show(area.ToString(), "Площадь выделенных граней API7");
//-------------------------------------------------------------------------------------------------------
        }

        private void button5_Click(object sender, EventArgs e)
        {
            IApplication app = (IApplication)Marshal.GetActiveObject("KOMPAS.Application.7");
            IKompasDocument document = app.ActiveDocument;
            IKompasDocument3D kompasDocument3D = (IKompasDocument3D)app.ActiveDocument;
            IFeature7 feature7 = (IFeature7)kompasDocument3D.TopPart;

            //просто накидаем переменных в 3D деталь
            IVariable7 iVariable7 = ((IPart7)feature7).AddVariable("D_test", 23, "диаметр");
            iVariable7.External = true;
            iVariable7 = kompasDocument3D.TopPart.AddVariable("_test1", 1, "просто так");
            iVariable7.External = true;
            iVariable7 = kompasDocument3D.TopPart.AddVariable("_test2", 1111, "не внешняя");
            kompasDocument3D.RebuildDocument();

            string msg = "";
            foreach (IVariable7 item in GetArrObject(feature7.Variables[true,false]))
            {
                msg = String.Concat(msg, string.Format("■ имя: {0}\n\u00A0\u00A0 ▪ значение: {1}\n", item.Name, item.Value));
            }
            MessageBox.Show(msg.ToString(), "Внешние переменные API7");
        }