Drawing Manipulator Class

HOOPS Communicator offers great support for BIM workflows with its ability to import all the major 3D and 2D formats as well as dedicated functionality that makes it easy to build web applications in the Building & Construction space. However, while working primarily with a “single source of truth” 3D model is the ideal case for BIM the reality is that in a typical building project there are still a lot of 2D drawings generated by different stakeholders that only exist as images or 2D PDF’s. While it is trivial to display this type of 2D data in a web-browser with open source libraries like PDF.js it is often desirable to combine them with the 3D model. This is what this class is about.

This operator allows you to drag & drop images or 2D PDF’s into your viewer window and add them to the 3D scene. From there you can then adjust the size and orientation of those drawings to easily match them up with the 3D model.


myDrawingManipulator = new DrawingManipulator(hwv);
myOperatorHandle = hwv.operatorManager.registerCustomOperator(myDrawingManipulator);

Creates a new DrawingManipulator object and registers it as an operator.


Creates a drop area for dragging & dropping images or PDF files into the viewer. If dropdiv is not specified the default HC div is used (‘content’).

let drawingnode = myDrawingManipulator.addImage(data, width, height);

You can directly pass your image data with the above function. The function will return the nodeid of the new drawing.

Returns an array of drawing nodeids.

Activates the drawing and enables its cutting plane

Deactivates a drawing and disables its cutting plane

Shows the pivot handles. Pivot handles allow you to easily align a drawing with the 3D model. To use them drag the handles to key points on the image. After they are positioned they can then be aligned with the 3D model by holding down shift while dragging.

While the Drawing Manipulator is active you can also ctrl-click to align the drawing with a given surface on the 3D model.

Shows the drawing handles to move the drawing back and forth along its axis and to rotate it manually.


Disables all handles

Aligns the camera with the currently active drawing

Below is the main code for the DrawingManipulator class. Besides requiring the HOOPS Web Viewer libraries, PDF.js is required for 2D PDF support:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js"></script>

It is important to note that this code is not production-ready and provided “as-is”. It is really meant as a starting point for your own development and as an example for some of the functionality and concepts used in HOOPS Communicator.

If you have any questions or comments or found a bug, please don’t hesitate to post them here in the forum.

DrawingManipulator.js (23.9 KB)
ViewerUtility.js (5.6 KB)


Thanks for great article.
But how can I use your js source in “hoops_web_viewer_sample.html”?

Below is a self-contained example that shows the usage of this class. After placing an scs file (e.g. arboleda) into the models directory simply start with:

Then you can just drag & drop a pdf or image onto the canvas to display it as a drawing aloongside the 3D model. I have added a separate menu to active the current drawings and the various option to change its position and orientation.

I hope this helps,

drawingmanipexample.zip (5.2 MB)

I have also made a slight bugfix to the existing class which can be downloaded here (it is already included in the project above):
DrawingManipulator.js (23.9 KB)

excuteme, do you have any tutorial video? It very helpfull but i don’t nkow how to do.

1 Like

I have made a quick video that illustrates how to use the drawingmanipulator that works with the 3dsandbox snippet below. I have also included the drawing used in this video:


1 Like

Can you calculate the projected area?

Can you elaborate? What projected area are you referring to?

like this . i need the projected area

It would be fairly easy to project the mesh onto the three major planes and display the result visually but if you are looking for calculating the exact 2d area of the projected mesh, that is not trivial for complex meshes I think and HOOPS Communicator does not have a function to accomplish this directly.

1 Like

I need to calculate the projected area of an object like this. Is there any function in C# that can help me with this? Or are there any similar methods available?

Does Hoop support accessing the vertices and polygons of an object ?

Yes, all of our products (HOOPS Visualize, Exchange and Communicator) give you access to the vertices and triangles/polygons of a piece of geometry.

With regard to getting the projected area, once again we have no direct function to calculate this but what you could do is use an offscreen image, project the model to the desired plane and then simply count the pixels of the resulting image. That would give you a fairly good approximation of the projected area. Both HOOPS Visualize and HOOPS Communicator support offscreen image generation.

1 Like

Could you guide me on how to obtain the vertices and triangles/polygons using a hoop and provide any instructional resources for that?

In the example below (which display the tessellation for a mesh), you can see how to extract the vertices and triangles of a mesh in HOOPS Communicator:

Documentation for the relevant function can be found here:

I’m assuming, you are interested in HOOPS Communicator, but let me know if you need similar information for HOOPS Visualize.

1 Like

Below is a modified sandbox example that shows how to retrieve line data from a mesh:


What I mean is, is there a way to determine the coordinates (Oxyz) of the ‘starting point’ and ‘ending point’ of a ‘Line’?

If you look at the code below, the start and endpoint of the line (assuming the line is not closed) will be the first and last point in the line data array.

  let data = await hwv.model.getNodeMeshData(nodeid);
    for (let i = 0; i < data.lines.elementCount; i++) {
        let lineData = [];
        let line = data.lines.element(i);
        let pp = line.iterate();
        for (let j = 0; j < line.vertexCount; j++) {            
            let rawpoint = pp.next();
            let p = new Communicator.Point3(rawpoint.position[0], rawpoint.position[1], rawpoint.position[2]);
            p = matrix.transform(p);

I think you you have to tell me a bit more about your use-case. Is the user selecting the line, or do you go through all the meshes to find lines?

If you are selecting a line in the viewer, then you can retrieve info about the line entity with the following sequence of calls (assuming the line is already selected):

let selectionItem = hwv.selectionManager.getLast();
let line =  selectionItem.getLineEntity();
let points = line.getPoints();

You can also find out what the type of line is, based on the nodeid of the mesh and the id of the line element. Given the above code you would continue:

let edgeProps = await hwv.model.getEdgeProperty(selectionItem.getNodeId(), line.getLineId());
if (edgeProps instanceof Communicator.SubentityProperties.LineElement) {
      //its a line
else if (edgeProps instanceof Communicator.SubentityProperties.CircleElement) {
     //its circular

Hope this helps

1 Like

Below is a function that calculates the rotation matrix between two vectors. You can use that to rotate the camera (or another object) towards the vector representing the line. Please see the sandbox example below:


 function ComputeVectorToVectorRotationMatrix(p1, p2) {
        const EPSILON = 0.0000001;
        let p3 = Communicator.Point3.cross(p1, p2);

        let dprod = Communicator.Point3.dot(p1, p2);
        let l = p3.length();

        // Construct a perpendicular vector for anti-parallel case
        if (l > -EPSILON && l < EPSILON) {
            if (dprod < 0) {
                if (p1.x < -EPSILON || p1.x > EPSILON) {
                    p3.x = p1.y;
                    p3.y = -p1.x;
                    p3.z = 0;
                } else if (p1.y < -EPSILON || p1.y > EPSILON) {
                    p3.x = -p1.y;
                    p3.y = p1.x;
                    p3.z = 0;
                } else if (p1.z < -EPSILON || p1.z > EPSILON) {
                    p3.x = -p1.z;
                    p3.z = p1.x;
                    p3.y = 0;
                } else {
                    return new Communicator.Matrix();
            } else {
                return new Communicator.Matrix();
        var ang = Math.atan2(l, dprod);
        ang *= (180 / Math.PI);

        return Communicator.Matrix.createFromOffAxisRotation(p3, ang);
1 Like

Thank you so much for your support !!!
I noticed on Hoops there is support for calculating the surface area and volume from the part.Body. How can I access or retrieve these two values using a function or method in Hoops?

Those values are among the properties returned by the getNodeProperties() function. See example below: