Monthly Archives: March 2014

Tables in MultiCAD.NET. Part 1: Generating reports based on table templates

Tables_20_en

With this post, we’re beginning a series of articles about features and details of the MultiCAD.NET API for creating and modifying table entities.

For many drawings, tables are indispensable: they’re used to present descriptions, specifications, and instructions for creating construction elements represented in a drawing. It’s common to create tables based on properties extracted from drawing objects. Automating this process can save time and reduce errors.

As an example, let’s consider generating a report that contains a list of socket properties extracted from an electric map (a drawing that illustrates socket placement for a number of rooms.) Each socket is marked by a note that contains the following text data:

  • socket type,
  • code number/manufacturer,
  • room number.

Tables_14

The algorithm to create the table can be divided into three steps:

  • creating the custom report template,
  • loading the template and filling the table with data,
  • breaking the entire table into a number of pages and inserting the pages.

Creating the table template

Usually table reports are based on standard templates that are created with the tables UI. For demonstration purposes we are going to create a custom template using the MultiCAD.NET API, so that the whole table will look as follows:

Tables_15_en

Each cell value represents the number of sockets of a specific code in a specific room. Also, the table contains a page header that could be added for each page and a header for the first page with the table’s title.

Here is an example of the method that creates the template and saves it to a file with a specified name:

Users will be able to change the suggested table’s structure and cell formatting in the table editor.

This implementation of the table contains cells with special string identificators: #code and #room. These strings help to find the correct place for the data when the table is being filled. This ensures the table will be filled properly even if the numbers of rows or columns are changed.

Constructing a report

An algorithm for report building can be divided into the following steps:

  1. adding the command for creating the report
  2. selecting all the notes for multilayered constructions that contain description for sockets,
  3. loading the template and open the table editor to provide the ability to make changes in the template manually,
  4. structuring the data from the selected objects,
  5. filling in the table headers (the table’s title and column names),
  6. filling in the rows.

Here is the entire code for the example, with a discussion of key points:

Adding the command for creating the report

We will add the key method that is the handler for the smpl_CreateTableReport command and implements the algorithm:

Selecting objects

Selecting all notes for multilayered constructions can be performed using object filter:

As a result we will get an array of Ids for all notes in the drawing. Using these Ids we can obtain a text string of each note:

To simplify filling up the table, all text data should be arranged in an single structure that supports searching and sorting operations. Here the following structure of nested dictionaries is used: <product_code<room_number, count=”">>.

Loading the template

Let’s assume that the template is already created and saved to an external file (for example, C:\template.dat file) using the CreateTemplate() method. Now the saved table can be loaded using the McTable.LoadFromFile() method. Let’s create a table object, read the saved table into it and launch the table editor. It’s important to note that the table must be saved in a format that can keep the table’s structure and formatting, as well as its contents.

Tables_16_en

After that we can switch to filling up the table. The process includes sorting data received from the notes strings and adding them in appropriate cells. There is a quite wide list of possible implementations, one of which you can find in the example’s source code.

Page division

MultiCAD.NET contains an effective ability to divide a table into multiple fragments without losing its integrity. It’s used to split a large table in order to place it on a smaller sheet of paper, while still being able to edit it as a whole. To insert a page breaks by maximum page height the McTable.PagesTable.SetPageHeight() is used.

The following code fragment divides the table into separable pages so that the total height of the filled rows of each page should be less than 50 mm:

Tables_19_en

Another option is to insert a page break by a row index using the McTable.PagesTable.SetPageBreak() method. For example, to insert a page break after the row with index 7:

The result table will contain two pages:

Tables_18_en

After the table is divided, insertion points for each page need to be set. The points are set relative to the table’s insertion point using the McTable.PagesTable.SetOriginPage() method. The first parameter of the method is a page index, and the second parameter is the page insertion point. For example, to insert pages with the interval of 5:

Loading the example application to AutoCAD

Like any MultiCAD application, the example can simply run in nanoCAD after loading the example’s assembly and calling the registered smpl_CreateTableReport command. To run the MultiCAD application in AutoCAD, it’s required to use the special Object Enabler application. It’s important to note that the standard MultiCAD Enabler for AutoCAD (which is available in the nanoCAD Developers’ Club) doesn’t support objects from the Multicad.Symbols namespace. For running applications that deal with such objects, SPDS GraphiCS or MechaniCS (that contain full set of primitives including table and note entities) should be launched first.

Selecting and editing custom entities in MultiCAD.NET

00

In the previous post we discussed the process for creating custom entities in the MultiCAD.NET API, and described the CustomObjects example from the SDK. In this post we’re going to focus on the issue of selecting custom entities of the same type in the drawing.

The CustomObjects example creates custom entities that display as framed text strings:

TextInBox entities

TextInBox entities with initial text strings

We’ll extend the code for the CustomObjects example by adding functionality to searching for one or more of these entities and changing the text for each of them.

In MultiCAD.NET, when selecting a single object in the drawing, the object manager’s method SelectObject() is used. The method has the following signatures:

Both methods allow the user to select an object based on a prompt shown in the command line. The second method adds an additional parameter for the coordinates of the selection point.

For selecting multiple objects, the following methods are used:

The first method selects drawing objects using a specific filter, the second one shows a prompt in the command line and allows the user to pick objects by themself.

The filter is represented by an ObjectFilter object and defines the selection criteria: object type, documents, layers, sheets or area for searching objects. In the following example, the SelectCircles command gets a list of circle objects that are on the current sheet and intersect a specified rectangular area:

To find all circle entities from the entire drawing (not only on the current sheet), the drawing’s document should be set as a search area:

The second method allows the user to select entities manually instead of using filters, but we need to make sure the user has selected only entities of desired type.

Here we create a new command called TextInBoxEdit that allows user to select a set of any entities, then filters out only TextInBox entities from the set and changes text for all of them:

Let’s see how it works.

The command prompts the user to select entities on the drawing:

05_en

User-selected objects

After the command’s execution, the text strings have been changed in all selected TextInBox entities:

04

TextInBox entities with changed text strings

Creating custom entities in CAD with MultiCAD .NET API

One of the key disadvantages of classical .NET APIs in .dwg-compatible CAD programs is that it is impossible to create custom entities in .NET. Custom entities must be created in C++ with managed C++/CLI wrappers to be usable in .NET .

Our MultiCAD .NET technology provides the ability to create custom entities within the bounds of managed code. In addition to not requiring intermediate C++ objects, MultiCAD .NET uses standard .NET mechanisms, so there is no need to manually serialize objects, create COM objects, or perform other overhead chores that are typical with CAD programming.

The CustomObjects sample application, delivered with the SDK, provides a good example of how  MultiCAD .NET works. This application creates a custom entity, TextInBox, that draws a framed text string:

TextInBox sample entity

TextInBox sample entity

A drawing containing this custom entity can be opened by any .dwg-compatible CAD program. The entity can be modified by loading an assembly, containing the entity’s code. The same assembly can be correctly loaded to all supported CAD platforms without recompiling.

MultiCAD .NET technology runs natively in nanoCAD, and works in AutoCAD (and other compatible CAD programs) through an Object Enabler extension module, which can be downloaded in the nanoCAD Developers’ Club.

Defining a custom entity class

To create a new custom entity type, it’s necessary to define a new class, derived from McCustomBase (the base class for all custom entities.) Two attributes are required for the defined class:

  1. [CustomEntity] attribute with specified class type, its GUID, the name that will be used for all such entities in the drawing’s database and the local name,
  2. [Serializable] attribute allows for using the standard serialization mechanism from .NET Framework.

The following code defines the TextInBox custom entity class:

The methods from the base McCustomBase class for drawing entity geometry, adding into the database, selecting, and modifying the object are overridden by the TextInBox class.

Drawing geometry

The OnDraw() method is used for drawing the object. This method uses the GeometryBuilder class as a parameter.

Adding an entity into a drawing, with interactive coordinate input

The PlaceObject() method is used for adding custom entities into the drawing. Apart from its primary purpose, this method is also used for interactive coordinate input. In the MultiCAD API, interactive input is implemented in the InputJig class, which contains all essential functionality:

  • public InputResult GetPoint(string prompt) — gets a point on the drawing from user input. The prompt parameter is used to show a prompt.
  • public void ExcludeObject(McObjectId ObjectId) — excludes a specified object from snap. (This can be used to prevent an object from snapping itself.)
  • public EventHandler MouseMove — the mouse movement event handler, used for monitoring mouse motion and interactive object redrawing.

This code implements the PlaceObject method:

Editing and Modifying Object

To add object-modifying and text-editing features to the TextInBox class, the following methods from the base class are overridden:

  • public virtual List OnGetGripPoints() — get the list of object’s grip points (the marked points on the object that are used for transforming the object.)
  • public virtual void OnMoveGripPoints(List indexes, Vector3d offset, bool isStretch) — the grip points moving event handler.
  • public virtual void OnTransform(Matrix3d tfm) — defines object transformations.
  • public virtual hresult OnEdit(Point3d pnt, EditFlags lInsertType) — the object editing event handler.

This code sets the grip points to the box corner points input by the user:

When the custom entity is selected, the grip points are shown:

TextInBox_02_en

This event handler code allows the grip points to be moved by dragging:

The indexes parameter is a list of grip points indexes, and offset is a grip points displacement vector.

The OnTransform() method calculates the new positions of both corner points after transformations:

And finally, a text string editing method is required. Editing can be initiated by double-clicking on the entity, or by choosing the proper item from the context menu. Once the edit command is called, the form with text field appears to enable setting a new value for the text string:

TextInBox_03_en

TextInBox edit form

Adding Object Properties to the Property Inspector

The MultiCAD .NET API provides the ability to add the properties of a custom entity to a property inspector regardless of the platform used for opening the .dwg file, be it AutoCAD or nanoCAD. This can be done by adding the following attributes to the appropriate public property:

  • DisplayNameAttribute — defines the property name for displaying in the inspector;
  • DescriptionAttribute — property description;
  • CategoryAttribute — defines the name of the category for the property.

Use this feature to add the Text property to the properties palette:

This will display the contents of the entity’s text component in the property inspector:

TextInBox_05_en

Text property shown in the inspector

In this example, we have created a custom entity that can be added to the .dwg drawing and standard modifications for CAD users. This set of entities’ features can be extended as well. In later articles we’ll talk about creating entity versions by adding new fields and by renaming (removing) existing fields, and discuss the specifics of entity versioning in MultiCAD.NET API.

Welcome!

Welcome to nanoCAD API blog. The blog is dedicated to nanoCAD programming and customization and intended for sharing information about using different kinds of our APIs for CAD application development. Here you will be able to find up-to-date information about our products, technical details, how-to solutions and of course sample code.

If you have any suggestions or ideas for blog topics, please feel free to put them forward in comments or at developer_support@nanocad.com.