MultiCAD.NET: calculation of the total length of the segments in the drawing



    The question often comes to our technical support: “How to calculate the sum of the lengths of the segments (pipeline sections, electrical circuit elements, etc.) in the drawing?”. There are many ways to solve this problem, in today's publication we will consider the implementation of the application on the MultiCAD.NET API, summing lengths, which works in nanoCAD, AutoCAD and ZWCAD. As an example, we take the task of determining the total length of pipes in the water supply scheme and consider two options for choosing the elements for counting: custom and the created filter.

    Determining the sum of the lengths of segments selected by the user


    Before proceeding to determine the length of a segment, it is necessary to determine what a segment is in MultiCAD.NET. A line is a standard primitive along with a circle, text, spline, etc. To represent a line in the drawing database, a class DbLinefrom the namespace of all primitives is used Multicad.DatabaseServices.StandardObjects.

    Objects DbLineas properties contain the start and end points, but do not contain information about the length of the segment. Of course, the coordinates of the points of the segment are enough to calculate its length, but it will be more convenient to use its geometric representation - an object of the class LineSeg3d(access to which is provided by the property DbLine.Line) and its property Lengthto obtain the length:

    double length = line.Line.Length;
    

    So, we will consider the first version of the application, when the user is prompted to choose segments for calculating the final length value. To implement custom object selection, the object SelectObjectsmanager class method will be used McObjectManager:

    public static McObjectId[] SelectObjects(string sPromt);
    

    The method displays a hint to the console and allows the user to select objects himself, the IDs of the selected objects are written to the array. Then the array elements are recognized, and for objects that are segments, we get the length and increment the result. General view of the team that implements this procedure:

    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);
    }
    

    In addition to line segments in the drawings, polylines are used, which are a combination of segments and / or arc elements. You can get the length of the polyline in the same way, using the geometric representation of the primitive - the class Polyline3dthrough the property Polyline:

    double length = polyline.Polyline.Length;
    

    Automatic calculation of the total line length


    In practice, when a drawing contains a large number of elements and you want to eliminate user input errors, objects can be selected automatically using the object filter. When creating a filter, the necessary criteria are indicated: the area of ​​the selection of objects (sheets, layers, documents, area, etc.) and types of objects.
    For example, in order to select all the lines on a specific layer, a filter is used with the name of the layer:

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

    The most common example in practice of using automatic calculation of the total length of lines is a report on the type of pipe in the water supply scheme.



    In our example, the pipeline scheme is organized in such a way that pipes of each type are located on separate layers: “Circuit 1” and “Circuit 2”.
    The next command generates a text report indicating all types of pipes located on separate layers and their total length.

    [CommandMethod("createReport", CommandFlags.NoCheck | CommandFlags.NoPrefix)]
    public void createReport()
    {
      List 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();
      }
    }
    

    The total length is calculated and the report lines are filled in in the method getLengthSumByLayer(), the code of which is presented below:

    public List getLengthSumByLayer()
    {
      List reportStrings = new List();
      // Получаем все слои на чертеже
      List layers = McObjectManager.CurrentStyle.GetLayers();
      foreach (string layerName in layers)
      {
        ObjectFilter filter = ObjectFilter.Create(true).AddType(typeof(DbLine)).AddType(typeof(DbPolyline)).AddLayer(layerName);
        List 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;
    }
    


    After executing this command, a report of the form will be added to the drawing: The



    detailed procedure for loading MultiCAD.NET applications can be found in our article Step-by-step overview: a single MultiCAD.NET application in nanoCAD, AutoCAD, ZWCAD .

    You can also discuss the article on our forum .
    Translation of the article into English: MultiCAD.NET: Calculating the total length of lines .

    Also popular now: