Drawings SDK Developer Guide > Working with .dwg Files > Working with Entities > Working with Specific Entitites > Working with Multi-Lines > Example of Working with the Multi-Line Object
Example of Working with the Multi-Line Object

This example demonstrates displaying and modifying the properties of a multi-line object. This example uses a console menu that represents the following operations: adding a new vertex [A], relocating an existing vertex [L], deleting the last vertex [D]; getting and setting the multi-line style [S], justification [J], scale factor [F], normal [N], closed line status [C], start caps suppression [B], and end caps suppression [E]; searching a line using a specified coordinates [G]; displaying the object properties, general entity properties, and specific properties [P]; and modifying the general entity properties [M].

The example uses the following header files, examples, and the functions implemented in them:


#include "..\Common\DemoMain.h"
#include "DbMLine.h"
#include <iostream>
using namespace std;

// Example of Entering and Displaying for Multi-Line Justification
bool EntryMLineJustify(OdInt16& refMode);
OdString AboutMLineJustify(Mline::MlineJustification mode);

// Example of Entering and Displaying 3D Point Objects
bool EntryPoint3d(OdGePoint3d& point);
OdString AboutPoint3d(const OdGePoint3d& point);

// Example of Entering and Displaying 3D Vector Objects
bool EntryVector3d(OdGeVector3d& vector);
OdString AboutVector3d(const OdGeVector3d& vector);

OdString AboutEntityPlane(OdDbEntity* pEntity);
void PrintEntityProperties(OdDbEntity* pEntity);
void ModifyEntityProperties(OdDbEntity* pEntity);

The PrintMLineProperties() function requires a pointer to an existing multi-line object and displays its specific properties. The function gets the specific properties using the style(), justification(), scale(), normal(), closedMline(), supressEndCaps(), and supressStartCaps() methods. The function gets the number of vertices using the numVertices() method and organizes a loop for printing the vertices, axes, and miters using the vertexAt(), axisAt(), and miterAt() methods appropriately. The function uses the AboutPoint3d() function for converting the coordinates of the vertices to a string value and the AboutVector3d() function for converting the coordinates of the normal, axes, and miters to a string value. The AboutPoint3d() and AboutVector3d() functions require an instance of the three-dimensional point or three-dimensional vector to be converted as an argument and return a string containing the X,Y,Z coordinates.

The PrintMLineProperties() function has the following implementation:


void PrintMLineProperties(OdDbMline* pMLine)
{
  int index = 0, count = pMLine->numVertices();

  wcout << L"\n  Normal = " << AboutVector3d(pMLine->normal())
        << L"\n  Style = " << AboutDbObject(pMLine->style())
        << L"\n  Scale factor = " << pMLine->scale()
        << L"\n  Justification = " << AboutMLineJustify(pMLine->justification())
        << L"\n  Closed status = " << ((pMLine->closedMline()) ? L"On" : L"Off")
        << L"\n  End caps suppression = " << ((pMLine->supressEndCaps()) ? L"On" : L"Off")
        << L"\n  Start caps suppression = " << ((pMLine->supressStartCaps()) ? L"On" : L"Off")
        << L"\n  Vertices and Segments [" << count << L"]:";

  while(index < count)
  {
    wcout << L"\n  " << index << L". " << AboutPoint3d(pMLine->vertexAt(index))
          << L" axis " << AboutVector3d(pMLine->axisAt(index))
          << L" miter " << AboutVector3d(pMLine->miterAt(index));
    index++;
  }
}

The ModifyMLineProperties() function requires a pointer to an existing multi-line object and implements a console menu for the listed operations. The function organizes a loop that inquires about the operation code and uses the switch statement to select whether the case must be performed. The function processes user actions in the loop until the user selects the [Q] operation. The function uses the EntryPoint3d() function for entering coordinates of a three-dimensional point and the EntryVector3d() function for entering coordinates of a three-dimensional vector. The EntryPoint3d() and EntryVector3d() functions require a reference to an instance of the three-dimensional point or three-dimensional vector to be modified as an argument and return True when the passed instance is modified successfully or False when the user cancels entry.

When the user selects [P], the function displays the common object properties using the PrintObjectProperties() function, general entity properties using the PrintEntityProperties() function, and specific multi-line properties using the PrintMLineProperties() function. When the user selects the [p] operation, the function displays only specific multi-line properties.

When the user selects [S], the function gets the object ID of the current multi-line style assigned for the multi-line entity using the style() method and calls the EntryDictionaryObject() function for selecting another style. The EntryDictionaryObject() function requires the object ID of the dictionary object storing the multi-line styles and the default multi-line style object as arguments, and returns the object ID of the multi-line object specified by the user or the same object ID if the user cancels entry. To get the dictionary of multi-line styles, the function uses the getMLStyleDictionaryId() method of the database object and the database() method of the multi-line object. The EntryDictionaryObject() function organizes its own console menu for selecting the object. After selection, the ModifyMLineProperties() function checks whether the ID is not kNull, and then, it calls the setStyle() method and passes to it the returned object ID to associate the multi-line with the returned style.

When the user selects [J], the function gets the current justification using the justification() method and displays its number. Then, the function calls the EntryMLineJustify() function for selecting a new justification. The EntryMLineJustify() function organizes a loop and requests the justification number. If the user selects a justification, this function returns True and the ModifyMLineProperties() function sets the new justification using the setJustification() method and displays information about it using the AboutMLineJustify() function, passing to it the number.

When the user selects [F], the function gets the current scale factor using the scale() method and requests a double value. If an entered value is incorrect, the function displays an error message and breaks to the console menu. If an entered value is correct, the function sets the new scale factor using the setScale() method.

When the user selects [N], the function gets the normal to the plane of the multi-line using the normal() method, calls the EntryVector3d() function for entry of its coordinates, and sets the returned vector as a new normal using the setNormal() method if entry is successful.

When the user selects [C], the function requests the new closed line status and prompts: N-on or F-off. The function calls the setClosedMline() method and passes to it a True value if the user enters 'N' or a False value if the user enters 'F'. After setting, the function checks and displays the closed status using the closedMline() method.

When the user selects [B] or [E], the function requests the start or end caps suppression and prompts: N-on or F-off. The function calls the setSupressStartCaps() or setSupressEndCaps() method and passes to it a True value if the user enters 'N' or a False value if the user enters 'F'. After setting, the function checks and displays the caps suppression status using the supressStartCaps() or supressEndCaps() method appropriately.

When the user selects [A], the function requests the coordinates of a new vertex and calls the EntryPoint3d() function for entry. If entry is successful, the function calls the appendSeg() method and passes to it the specified point to append a new vertex at the end of the multi-line.

When the user selects [D], the function calls the removeLastSeg() method and passes to it the three-dimensional point instance to save coordinates of the last vertex to be deleted from the multi-line. Then, the function displays the coordinates of the deleted vertex and number of vertices.

When the user selects [L], the function requests the index of the vertex to be relocated. If an entered value is incorrect or out of range, the function displays an error message and breaks to the console menu. If an entered value is correct, the function requests the coordinates of a new position for the vertex and calls the EntryPoint3d() function. If entry is successful, the function calls the moveVertexAt() method and passes to it the index as the first argument and a three-dimensional point instance as the second argument. Then, the function displays the coordinates of the vertex, axis, and miter.

When the user selects [G], the function requests the coordinates of a point and calls the EntryPoint3d() function for entry. If entry is successful, the function calls the element() method and passes to it the specified point for which to search for the line on which this point lies. The element() method returns the line index if the searching is successful or (–1) if the line is not found, that is, if the point does not lie on a line. Then, the function displays the result of this finding.

When the user selects [M], the function calls the ModifyEntityProperties() function and passes to it the pointer to the multi-line object for modifying its general entity properties. After modification, the function displays all multi-line properties using the [P] operation.

The ModifyMLineProperties() function has the following implementation:


void ModifyMLineProperties(OdDbMline* pMLine)
{
  wchar_t ch = L'\0';
  double value;
  OdInt16 justify;
  OdInt16 index, count;
  OdGePoint3d point;
  OdGeVector3d vector;
  OdDbObjectId idStyle;

  wcout << L"\n\nStart modifying of the multi-line properties";

  do {
    switch(ch)
    {
      case L'M':          // Modify the general properties
      case L'm':
        ModifyEntityProperties(pMLine);


      case L'P':          // Print the whole properties
        wcout << L"\nH=" << pMLine->handle().ascii();
        wcout << L"\n  ------ Common Object Properties";
        PrintObjectProperties(pMLine);
        wcout << L"\n  ------ General Entity Properties";
        PrintEntityProperties(pMLine);


      case L'p':          // Print the specific properties
        wcout << L"\n  ------ Specific Multi-Line Properties";
        PrintMLineProperties(pMLine);
        wcout << L"\n";        
        break;


      case L'G':          // Get the line index (by order)
      case L'g':
        wcout << L"Entry the coordinates to find";
        if(EntryPoint3d(point.set(0,0,0)))
        {
          index = pMLine->element(point);
          if(index != -1)
            wcout << L"Point belongs to the line " << index << L"\n";
          else
            wcout << L"Line is not found\n";
        }
        break;


      case L'A':          // Append a new vertex
      case L'a':
        count = pMLine->numVertices();
        wcout << L"Entry a new vertex (" << count << L")";

        if(EntryPoint3d(point.set(0,0,0)))
        {
          pMLine->appendSeg(point);
          wcout << L"New vertex is set to: " << AboutPoint3d(pMLine->vertexAt(count)) << L"\n";
        }
        break;


      case L'L':          // Relocate the vertex
      case L'l':
        count = pMLine->numVertices()-1;
        wcout << L"Entry vertex/segment index [0..." << count << L"]:>";
        wcin >> index;

        if(!wcin.fail() && wcin.peek() == 10)
        {
          if(index >= 0 && index <= count)
          {
            wcout << L"Relocate vertex";
            point = pMLine->vertexAt(index);
            if(EntryPoint3d(point))
            {
              pMLine->moveVertexAt(index, point);
              wcout << L"Vertex (" << index << L") to "
                    << AboutPoint3d(pMLine->vertexAt(index))
                    << L" axis " << AboutVector3d(pMLine->axisAt(index))
                    << L" miter " << AboutVector3d(pMLine->miterAt(index));
            }
          }
          else wcout << L"Error: Index outs the range\n";
        }
        else { wcin.clear();  wcin.sync();  wcout << L"Error: Invalid entered value\n"; }
        break;


      case L'D':          // Delete the last vertex
      case L'd':
        count = pMLine->numVertices()-1;
        pMLine->removeLastSeg(point);
        wcout << L"Vertex/segment (" << count << L") is deleted for "
              << AboutPoint3d(point) << L". Vertices = " << pMLine->numVertices();
        break;


      case L'N':          // Set the normal
      case L'n':
        wcout << L"Entry the normal";
        vector = pMLine->normal();
        if(EntryVector3d(vector))
        {
          pMLine->setNormal(vector);
          wcout << L"Normal is set to " << AboutVector3d(pMLine->normal()) << L"\n";
        }
        break;


      case L'J':          // Set the justification
      case L'j':
        wcout << L"\nCurrent justification = " << (justify = pMLine->justification());

        if(EntryMLineJustify(justify))
        {
          pMLine->setJustification((Mline::MlineJustification) justify);
          wcout << L"Justification is set to: " << AboutMLineJustify(pMLine->justification()) << L"\n";
        }
        break;


  	  case L'F':          // Set the scale factor
      case L'f':
        wcout << L"\nCurrent scale factor = " << pMLine->scale()
              << L"\nEntry a new factor:>";
        wcin >> value;

        if(!wcin.fail() && wcin.peek() == 10)
        {
            pMLine->setScale(value);
            wcout << L"Scale factor is set to: " << pMLine->scale() << L"\n";
        }
        else { wcin.clear();  wcin.sync();  wcout << L"Error: Invalid entered value\n"; }
        break;


      case L'S':          // Set the multi-line style
      case L's':
        idStyle = EntryDictionaryObject(pMLine->database()->getMLStyleDictionaryId(), pMLine->style());

        if(!idStyle.isNull())
        {
          pMLine->setStyle(idStyle);
          wcout << L"Style is set to: " << AboutDbObject(pMLine->style()) << L"\n";
        }
        else wcout << L"Entry is canceled\n";
        break;


      case L'C':          // Set the closed line status 
      case L'c':
        wcout << "\nSet the closed status [N-on|F-off]:>";
        wcin >> ch;

        if(ch == L'N' || ch == L'n') pMLine->setClosedMline(true);
        else if(ch == L'F' || ch == L'f') pMLine->setClosedMline(false);

        wcout << L"The closed status is set to: " << ((pMLine->closedMline()) ? L"On" : L"Off") << L"\n";
        break;


      case L'B':          // Set the start caps suppression (begin of line) 
      case L'b':
        wcout << "\nSuppress the start caps [N-on|F-off]:>";
        wcin >> ch;

        if(ch == L'N' || ch == L'n') pMLine->setSupressStartCaps(true);
        else if(ch == L'F' || ch == L'f') pMLine->setSupressStartCaps(false);

        wcout << L"Start caps suppression is set to: " << ((pMLine->supressStartCaps()) ? L"On" : L"Off") << L"\n";
        break;


      case L'E':          // Set the end caps suppression (end of line) 
      case L'e':
        wcout << "\nSuppress the end caps [N-on|F-off]:>";
        wcin >> ch;

        if(ch == L'N' || ch == L'n') pMLine->setSupressEndCaps(true);
        else if(ch == L'F' || ch == L'f') pMLine->setSupressEndCaps(false);

        wcout << L"End caps suppression is set to: " << ((pMLine->supressEndCaps()) ? L"On" : L"Off") << L"\n";
        break;


      case L'\0':         // Skip an action
        break;

      default:
        wcout << L"Incorrect operation\n";
    }
    wcout << L"\nG. Get the line index";
    wcout << L"\nA. Append a new vertex";
    wcout << L"\nL. Relocate the vertex";
    wcout << L"\nD. Delete the last vertex";
    wcout << L"\nN. Set the normal";
    wcout << L"\nF. Set the scale factor";
    wcout << L"\nJ. Set the justification";
    wcout << L"\nS. Set the multi-line style";
    wcout << L"\nC. Set the closed line status";
    wcout << L"\nE. Set the end caps suppression";
    wcout << L"\nB. Set the start caps suppression";
    wcout << L"\nP. Print the whole properties";
    wcout << L"\np. Print the specific properties";
    wcout << L"\nM. Modify the general properties";
    wcout << L"\nQ. Quit";
    wcout << L"\nSelect operation:>";
    wcin >> ch;
  }
  while(ch != L'Q' && ch != L'q');

  wcout << L"Stop modifying of the multi-line properties\n";
}

Testing gives the following results:


Start modifying of the multi-line properties

G. Get the line index
A. Append a new vertex
L. Relocate the vertex
D. Delete the last vertex
N. Set the normal
F. Set the scale factor
J. Set the justification
S. Set the multi-line style
C. Set the closed line status
E. Set the end caps suppression
B. Set the start caps suppression
P. Print the whole properties
p. Print the specific properties
M. Modify the general properties
Q. Quit
Select operation:>

When the operation is p-"Print the specific properties":


------ Specific Multi-Line Properties
Normal = (0,0,1)
Style = [Db:kNull]
Scale factor = 1
Justification = [1-Zero]
Closed status = Off
End caps suppression = Off
Start caps suppression = Off
Vertices and Segments [0]

When the operation is S-"Set the multi-line style":


List of the objects:
18-"Standard"
19-"MLStyle"
Current: [18-"Standard"]
Entry the name to be selected (or [?]-null/[:]-quit):>MLStyle
Style is set to: [19-"MLStyle"-MlineStyle]

When the operation is A-"Append a new vertex":


Select operation:>a

Entry a new vertex (0)
Current coordinates: (0,0,0)
Entry X-coordinate:>1
Entry Y-coordinate:>1
Entry Z-coordinate:>0
New vertex is set to: (1,1,0)

Select operation:>a

Entry a new vertex (1)
Current coordinates: (0,0,0)
Entry X-coordinate:>5
Entry Y-coordinate:>2
Entry Z-coordinate:>0
New vertex is set to: (5,2,0)

Select operation:>a

Entry a new vertex (2)
Current coordinates: (0,0,0)
Entry X-coordinate:>7
Entry Y-coordinate:>5
Entry Z-coordinate:>0
New vertex is set to: (7,5,0)

Select operation:>a

Entry a new vertex (3)
Current coordinates: (0,0,0)
Entry X-coordinate:>3
Entry Y-coordinate:>9
Entry Z-coordinate:>0
New vertex is set to: (3,9,0)

When the operation is F-"Set the scale factor":


Current scale factor = 1
Entry a new factor:>2.5
Scale factor is set to: 2.5

When the operation is C-"Set the closed line status":


Set the closed status [N-on|F-off]:>N
The closed status is set to: On

When the operation is E-"Set the end caps suppression":


Suppress the end caps [N-on|F-off]:>N
End caps suppression is set to: On

When the operation is B-"Set the start caps suppression":


Suppress the start caps [N-on|F-off]:>N
Start caps suppression is set to: On

When the operation is J-"Set the justification":


Current justification = 1
0. Top
1. Zero
2. Bottom
3. Quit
Entry the justification:>0
Justification is set to: [0-Top]

When the operation is p-"Print the specific properties":


------ Specific Multi-Line Properties
Normal = (0,0,1)
Style = [19-"MLStyle"-MlineStyle]
Scale factor = 2.5
Justification = [0-Top]
Closed status = On
End caps suppression = On
Start caps suppression = On
Vertices and Segments [4]:
0. (1,1,0) axis (0.970143,0.242536,0) miter (0.707107,0.707107,0)
1. (5,2,0) axis (0.5547,0.83205,0) miter (-0.576048,0.817416,0)
2. (7,5,0) axis (-0.707107,0.707107,0) miter (-0.995133,-0.0985376,0)
3. (3,9,0) axis (-0.242536,-0.970143,0) miter (0.266934,-0.963715,0)

When the operation is L-"Relocate the vertex":


Entry vertex/segment index [0...3]:>1
Relocate vertex
Current coordinates: (5,2,0)
Entry X-coordinate:>6
Entry Y-coordinate:>1
Entry Z-coordinate:>0
Vertex (1) to (6,1,0) axis (0.242536,0.970143,0) miter (-0.615412,0.788205,0)

When the operation is G-"Get the line index":


Entry the coordinates to find
Current coordinates: (0,0,0)
Entry X-coordinate:>4
Entry Y-coordinate:>1
Entry Z-coordinate:>0
Point belongs to the line 0

When the operation is D-"Delete the last vertex":


Vertex/segment (3) is deleted for (3,9,0). Vertices = 3

When the operation is N-"Set the normal":


Entry the normal
Current vector directions: (0,0,1)
Entry X-direction:>0.145381
Entry Y-direction:>0.843209
Entry Z-direction:>0.517556
Normal is set to (0.145381,0.843209,0.517556)

When the operation is P-"Print all properties":


H=40
  ------ Common Object Properties
  Type: AcDbMline
  Status: unerased,resident,modified,forRead,forWrite
  Database: c:\test.dwg
  ------ General Entity Properties
  Block: [1F-"*Model_Space"-Block]
  Layer: [10-"0"-Layer]
  Material: [44-"ByLayer"-Material]
  Linetype: [15-"ByLayer"-Linetype]
  Lineweight: [kLnWtByLayer]
  Transparency: [byLayer]
  Visual style: [Db:kNull]
  PlotStyleName: ByLayer
  Linetype scale: 1
  Color: [byLayer], Index = 256
  State: , Visible, Cast Shadows, Receive Shadows
  ------ Specific Multi-Line Properties
  Normal = (0.145381,0.843209,0.517556)
  Style = [19-"MLStyle"-MlineStyle]
  Scale factor = 2.5
  Justification = [0-Top]
  Closed status = On
  End caps suppression = On
  Start caps suppression = On
  Vertices and Segments [3]:
  0. (1,1,0) axis (1,0,0) miter (0.957092,0.289784,0)
  1. (6,1,0) axis (0.242536,0.970143,0) miter (-0.615412,0.788205,0)
  2. (7,5,0) axis (-0.83205,-0.5547,0) miter (-0.576048,-0.817416,0)  

Use the Q-"Quit" operation to exit:


Stop modifying of the multi-line properties

See Also

Working with Multi-Lines

Copyright © 2002 – 2021. Open Design Alliance. All rights reserved.