Diagram for .NET / User's Guide / Document Object Model / Models / Shapes / Composite Shapes

In This Topic
    Composite Shapes
    In This Topic

    Composite shapes are shapes, which aggregate multiple primitive models. Composite shapes are represented by the NCompositeShape class, which derives from the NShape class. You can use any primitive model(s) to represent the geometry of a composite shape. That is why composite shapes are often used for custom shapes. Composite shapes are by default treated as 2D shapes.

     Aggregated Primitives
    The primitives, which a composite shape aggregates are stored in an instance of the NPrimitiveModelCollection class, which can be obtained from the Primitives property. In this way the geometry of a composite shape can be represented by arbitrary paths and texts.
     Creating a custom shape

    The following example shows how to create the following custom shape:

    C#
    Copy Code
    NCompositeShape shape = new NCompositeShape();
    
    // create the cup as a polygon path
    NPolygonPath cup = new NPolygonPath(new NPointF[]{new NPointF(45, 268), new NPointF(63, 331), new NPointF(121, 331), new NPointF(140, 268)});
    shape.Primitives.AddChild(cup);
    
    // create the cup hangle as a closed curve path
    NClosedCurvePath handle = new NClosedCurvePath(new NPointF[]{new NPointF(175, 295), new NPointF(171, 278), new NPointF(140, 283), new NPointF(170, 290), new NPointF(128, 323)}, 1);
    NStyle.SetFillStyle(handle, new NColorFillStyle(Color.LightSalmon));
    shape.Primitives.AddChild(handle);
    
    // create the steam as a custom filled path
    GraphicsPath path = new GraphicsPath();
    path.AddBeziers(new PointF[]{new PointF(92, 258), new PointF(53, 163), new PointF(145, 160), new PointF(86, 50), new PointF(138, 194), new PointF(45, 145), new PointF(92, 258)});
    path.CloseAllFigures();
    
    NCustomPath steam = new NCustomPath(path, PathType.ClosedFigure);
    NStyle.SetFillStyle(steam, new NColorFillStyle(Color.FromArgb(50, 122, 122, 122)));
    shape.Primitives.AddChild(steam);
    
    // update the shape model bounds to fit the primitives it contains
    shape.UpdateModelBounds();
    
    // create the shape ports
    shape.CreateShapeElements(ShapeElementsMask.Ports);
    
    // create dynamic port anchored to the cup center
    NDynamicPort dynamicPort = new NDynamicPort(cup.UniqueId, ContentAlignment.MiddleCenter, DynamicPortGlueMode.GlueToContour);
    shape.Ports.AddChild(dynamicPort);
    
    // create rotated bounds port anchored to the middle right side of the handle
    NRotatedBoundsPort rotatedBoundsPort = new NRotatedBoundsPort(handle.UniqueId, ContentAlignment.MiddleRight);
    shape.Ports.AddChild(rotatedBoundsPort);
    
    // apply style to the shape
    shape.Style.FillStyle = new NColorFillStyle(Color.LightCoral);
    
    Visual Basic
    Copy Code
    Dim shape As New NCompositeShape
    
    ' create the cup as a polygon path
    Dim cup As NPolygonPath = New NPolygonPath(New NPointF() {New NPointF(45, 268), New NPointF(63, 331), New NPointF(121, 331), New NPointF(140, 268)})
    shape.Primitives.AddChild(cup)
    
    ' create the cup hangle as a closed curve path
    Dim handle As NClosedCurvePath = New NClosedCurvePath(New NPointF() {New NPointF(175, 295), New NPointF(171, 278), New NPointF(140, 283), New NPointF(170, 290), New NPointF(128, 323)}, 1)
    NStyle.SetFillStyle(handle, New NColorFillStyle(Color.LightSalmon))
    shape.Primitives.AddChild(Handle)
    
    ' create the steam as a custom filled path
    Dim path As New GraphicsPath
    path.AddBeziers(New PointF() {New PointF(92, 258), New PointF(53, 163), New PointF(145, 160), New PointF(86, 50), New PointF(138, 194), New PointF(45, 145), New PointF(92, 258)})
    path.CloseAllFigures()
    
    Dim steam As New NCustomPath(path, PathType.ClosedFigure)
    NStyle.SetFillStyle(steam, New NColorFillStyle(Color.FromArgb(50, 122, 122, 122)))
    shape.Primitives.AddChild(steam)
    
    ' update the shape model bounds to fit the primitives it contains
    shape.UpdateModelBounds()
    
    ' create the shape ports
    shape.CreateShapeElements(ShapeElementsMask.Ports)
    
    ' create dynamic port anchored to the cup center
    Dim dynamicPort As New NDynamicPort(cup.UniqueId, ContentAlignment.MiddleCenter, DynamicPortGlueMode.GlueToContour)
    shape.Ports.AddChild(dynamicPort)
    
    ' create rotated bounds port anchored to the middle right side of the handle
    Dim rotatedBoundsPort As New NRotatedBoundsPort(Handle.UniqueId, ContentAlignment.MiddleRight)
    shape.Ports.AddChild(rotatedBoundsPort)
    
    ' apply style to the shape
    shape.Style.FillStyle = New NColorFillStyle(Color.LightCoral)
    

    The coffee cup shape consist of three parts: cup, handle and steam. They are represented by three different types of primitives.

    It is important to remember that you must call the UpdateModelBounds method of the composite shape once you have finished adding primitives to it. This is necessary in order for the shape to adopt the bounds of the primitives it contains (see Models for more information about aggregate models bounds).

     Composition

    Composition is the process of creating of a new composite shape, which contains clonings of all the primitives contained in other shapes. This operation is primary used for the creation of a custom shape from a set of primitive shapes, but you can generally compose any set of shape - including other composite shapes. 

    This operation is implemented by the NBatchCompose class - the implementation internally calls the Compose method of each shape.

    Composition preserves the scene transformation of the original primitives. The cloned primitives adopt the style of the shapes, which contained the original primitives. The composed shapes must have a compose permission.

     Decomposition
    Decomposition is the process of creating of a primitive shape for each primitive model aggregated by a set of shapes. For example decomposing the coffee cup shape will create three shapes: one polygon shape, one closed curve path shape and one composite shape with a single custom path primitive (note that the there is currently no primitive shape, which can aggregate a single custom path).

    This operation is  implemented by the NBatchDecompose class - the implementation internally calls the Decompose method of each shape.

    It is the primitive models, not the shapes, which determine what type of shape must be created. That is why each primitive model is responsible for overriding the CreateShape method declared in the NPrimitiveModel class.

    Decomposition preserves the scene transformation of the primitives. If there is a local style applied to a primitive model it will be applied to the created shape. The decomposed shapes must have a decompose permission.
     Related Examples
    Windows Forms: Document Object Model - Shapes - Custom Shapes
    See Also