MultiCAD.NET: подсчет суммарной длины отрезков на чертеже

в 9:39, , рубрики: api, autocad, CAD/CAM, multicad.net, nanoCAD, zwcad, Блог компании Нанософт

MultiCAD.NET: подсчет суммарной длины отрезков на чертеже - 1

К нам в техподдержку часто приходит вопрос: «Как посчитать суммы длин отрезков (участков трубопровода, элементов электрических схем и т.п.) в чертеже?». Существует масса способов решения этой задачи, в сегодняшней публикации мы рассмотрим реализацию приложения на MultiCAD.NET API, суммирующего длины, которое работает в nanoCAD, AutoCAD и ZWCAD. В качестве примера мы возьмем задачу определения суммарной длины труб в схеме водоснабжения и рассмотрим два варианта выбора элементов для подсчета: пользовательский и по созданному фильтру.

Определение суммы длин отрезков, выбранных пользователем

Прежде чем приступить к определению длины отрезка, необходимо определить, что же такое отрезок в MultiCAD.NET. Отрезок является стандартным примитивом наряду с окружностью, текстом, сплайном и др. Для представления отрезка в базе данных чертежа используется класс DBLine из пространства имен всех примитивов Multicad.DatabaseServices.StandardObjects.

Объекты DBLine в качестве свойств содержат начальную и конечную точку, но не содержат информации о длине отрезка. Конечно, координат точек отрезка достаточно для вычисления его длины, но удобнее будет использовать его геометрическое представление — объект класса LineSeg3d (доступ к которому обеспечивает свойство DBLine.Line) и его свойство Length для получения длины:

double length = line.Line.Length;

Итак, рассмотрим первый вариант приложения, когда пользователю предлагается самостоятельно выбрать отрезки для вычисления итогового значения длины. Для реализации пользовательского выбора объекта будет использоваться метод SelectObjects класса менеджера объектов McObjectManager:

public static McObjectId[] SelectObjects(string sPromt);

Метод выводит подсказку в консоль и позволяет пользователю самому выбирать объекты, ID выбранных объектов записываются в массив. Затем производится распознавание элементов массива, и для объектов, которые являются отрезками, получаем длину и инкрементируем результат. Общий вид команды, реализующий эту процедуру:

CommandMethod("LineLengthSum", CommandFlags.NoCheck | CommandFlags.NoPrefix)]
public void LineLengthSum()
{
  // Получаем объекты выбором на чертеже
  McObjectId[] idSelecteds = McObjectManager.SelectObjects("Выберите объекты типа линия");
  
  if (idSelecteds.Length == 0)
  {
    MessageBox.Show("Объекты не выбраны");
    return;
  }
  
  double lengthSum = 0;
  foreach (McObjectId currID in idSelecteds)
  {
    // Получаем объект по ID
    McObject currObj = currID.GetObject(); 
				
    // Распознавание типа объекта 
    if (currObj is DbLine)
    {
      lengthSum += (currObj as DbLine).Line.Length;
    }
  }

  MessageBox.Show(lengthSum.ToString(), "Длина всех выбранных отрезков:", MessageBoxButtons.OK, MessageBoxIcon.Information);
}

Кроме отрезков прямых на чертежах используются полилинии, которые представляют собой совокупность отрезков и/или дуговых элементов. Получить длину полилинии можно аналогично, использую геометрическое представление примитива — класс Polyline3d через свойство Polyline:

double length = polyline.Polyline.Length;

Автоматический подсчет суммарной длины линий

На практике, когда чертеж содержит большое число элементов и требуется исключить ошибки пользовательского ввода, объекты могут быть выбраны автоматически, используя фильтр объектов. При создании фильтра указываются необходимые критерии: область выбора объектов (листы, слои, документы, область, и пр.) и типы объектов.
Например, для того, чтобы выбрать все линии на конкретном слое используется фильтр с указанием имени слоя:

ObjectFilter filter = ObjectFilter.Create(true);
filter.AddLayer("Холодная вода");
filter.AddType(typeof(DbLine));
List<McObjectId> ids = filter.GetObjects();

Наиболее часто встречающийся на практике пример применения автоматического подсчета суммарной длины линий — формирование отчета по типу труб на схеме водоснабжения.

MultiCAD.NET: подсчет суммарной длины отрезков на чертеже - 2

В нашем примере схема трубопровода организована таким образом, что трубы каждого типа расположены на отдельных слоях: «Контур 1» и «Контур 2».
Следующая команда формирует текстовый отчет с указанием всех типов труб, расположенных на отдельных слоях и их суммарной длины.

[CommandMethod("createReport", CommandFlags.NoCheck | CommandFlags.NoPrefix)]
public void createReport()
{
  List<String> reportStrings = getLengthSumByLayer();
  if (reportStrings.Count == 0)
  {
    MessageBox.Show("Схема не содержит элементов линий и полилиний");
    return;
  }

  // Отступ для вывода строки отчета
  int indent = 0;

  // Заголовок отчета
  DbText caption = new DbText();
  caption.Text = new TextGeom("Длина труб по типу", new Point3d(0, indent, 0), Vector3d.XAxis, "Standard", 10);
  caption.DbEntity.AddToCurrentDocument();

  foreach (String str in reportStrings)
  {
    indent -= 10;
    DbText reportText = new DbText();
    reportText.Text = new TextGeom(str, new Point3d(0, indent, 0), Vector3d.XAxis, "Standard", 6);
    reportText.DbEntity.AddToCurrentDocument();
  }
}

Подсчет суммарной длины и заполнение строк отчета производится в методе getLengthSumByLayer(), код которого представлен ниже:

public List<String> getLengthSumByLayer()
{
  List<String> reportStrings = new List<String>();
      
  // Получаем все слои на чертеже
  List<string> layers = McObjectManager.CurrentStyle.GetLayers();
  foreach (string layerName in layers)
  {
    ObjectFilter filter = ObjectFilter.Create(true).AddType(typeof(DbLine)).AddType(typeof(DbPolyline)).AddLayer(layerName);
    List<McObjectId> idSelected = filter.GetObjects();
    if (idSelected.Count != 0)
    {
      double lengthSum = 0;
      foreach (McObjectId currID in idSelected)
      {
        // Получаем объект по ID
        McObject currObj = currID.GetObject();

        // Распознавание типа объекта 
        if (currObj is DbLine)
        {
          lengthSum += (currObj as DbLine).Line.Length;
        }
        else if (currObj is DbPolyline)
        {
          lengthSum += (currObj as DbPolyline).Polyline.Length;
        }
      }

      // Если суммарная длина отрезков и полилиний на слое ненулевая, то добавляем в текст отчета
      if (lengthSum != 0)
      {
        reportStrings.Add(layerName.ToString() + ": " + lengthSum.ToString());
      }
    }
  }
  return reportStrings;
}

После выполнения данной команды на чертеж будет добавлен отчет вида:

MultiCAD.NET: подсчет суммарной длины отрезков на чертеже - 3

Подробную процедуру загрузки MultiCAD.NET приложений вы можете найти в нашей статье Пошаговый обзор: единое MultiCAD.NET приложение в nanoCAD, AutoCAD, ZWCAD

Обсудить статью можно также и на нашем форуме.

Автор: ISL

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js