public override void Calculate()
        {
            if (InputPorts[0].Data == null)
            {
                return;
            }

            var modelInfo = InputPorts[0].Data as ModelInfo;

            if (modelInfo == null)
            {
                return;
            }

            var model = modelController.GetModel(modelInfo.modelId) as IfcModel;

            if (model == null)
            {
                return;
            }

            // Get the model content
            xModel  = model.GetModel();
            context = model.xModelContext;

            // CREATE THE OPERATIONAL SPACE FOR DOORS
            var doors      = xModel.Instances.OfType <IIfcDoor>();
            var elementIds = new List <IfcGloballyUniqueId>();

            foreach (var item in doors)
            {
                elementIds.Add(item.GlobalId);
            }

            // control.InitViewPort();
            control.Visualize(control.CreateModelUiElementsDs(model, elementIds, false));

            foreach (var item in doors)
            {
                MeshBuilder meshBuilder = new MeshBuilder(false, false);


                // if (((IIfcDoorStyle)item.IsTypedBy.First().RelatingType).OperationType == IfcDoorStyleOperationEnum.DOUBLE_DOOR_SINGLE_SWING)
                // {

                var placement = ((IfcLocalPlacement)item.ObjectPlacement).PlacementRelTo.ReferencedByPlacements.First();
                var mat       = placement.ToMatrix3D();

                // Set the origin
                var x = mat.OffsetX;
                var y = mat.OffsetY;
                var z = mat.OffsetZ;

                var locPoint     = new Point3D(x, y, z);
                var allignVector = new Vector3D();
                var normalVector = new Vector3D();
                var heightVector = new Vector3D(0, 0, (double)item.OverallHeight);

                foreach (XbimShapeInstance instance in context.ShapeInstancesOf(item).Where(i => i.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsIncluded))
                {
                    allignVector = new Vector3D((double)(instance.Transformation.Left.X * item.OverallWidth), (double)(instance.Transformation.Left.Y * item.OverallWidth), (double)(instance.Transformation.Left.Z * item.OverallWidth));
                    normalVector = Vector3D.CrossProduct(allignVector, new Vector3D(0, 0, 1));
                }
                // allignVector.Negate();
                // Base Area
                // var listpoints = new List<Point>
                // {
                //     new Point(locPoint.X, locPoint.Y),
                //     new Point(locPoint.X + normalVector.X, locPoint.Y + normalVector.Y),
                //     new Point(locPoint.X + normalVector.X - allignVector.X, locPoint.Y + normalVector.Y - allignVector.Y),
                //     new Point(locPoint.X - allignVector.X, locPoint.Y - allignVector.Y)
                // };

                // var rec = new Rect3D(locPoint.X, locPoint.Y, locPoint.Z, Math.Abs(heightVector.X + allignVector.X + normalVector.X), Math.Abs(heightVector.Y + allignVector.Y + normalVector.Y), Math.Abs(heightVector.Z + allignVector.Z + normalVector.Z));
                //
                // meshBuilder.AddBox(rec);

                // var profile = new[] { new Point(0, 0.4), new Point(0.06, 0.36), new Point(0.1, 0.1), new Point(0.34, 0.1), new Point(0.4, 0.14), new Point(0.5, 0.5), new Point(0.7, 0.56), new Point(1, 0.46) };
                // meshBuilder.AddRevolvedGeometry(listpoints, null, locPoint, heightVector, 10);

                // meshBuilder.AddBox(new Rect3D(locPoint.X, locPoint.Y, locPoint.Z, Math.Abs(normalVector.X + allignVector.X), Math.Abs(normalVector.Y+ allignVector.Y), Math.Abs(normalVector.Z + allignVector.Z)));
                //meshBuilder.AddExtrudedGeometry(listpoints, new Vector3D(1,1,1), locPoint, Point3D.Add(locPoint, heightVector));
                // meshBuilder.AddExtrudedSegments(listpoints, new Vector3D(), locPoint, Point3D.Add(locPoint, heightVector));

                var listpoints3D = new List <Point3D>
                {
                    // 2D Rectangle
                    new Point3D(locPoint.X, locPoint.Y, locPoint.Z),
                    new Point3D(locPoint.X + normalVector.X, locPoint.Y + normalVector.Y, locPoint.Z),
                    new Point3D(locPoint.X + normalVector.X - allignVector.X, locPoint.Y + normalVector.Y - allignVector.Y, locPoint.Z),
                    new Point3D(locPoint.X - allignVector.X, locPoint.Y - allignVector.Y, locPoint.Z),

                    // 3D BOX
                    // new Point3D(locPoint.X, locPoint.Y, locPoint.Z),
                    // new Point3D(locPoint.X + normalVector.X , locPoint.Y + normalVector.Y, locPoint.Z),
                    // new Point3D(locPoint.X + normalVector.X - allignVector.X, locPoint.Y + normalVector.Y - allignVector.Y, locPoint.Z),
                    // new Point3D(locPoint.X - allignVector.X, locPoint.Y - allignVector.Y, locPoint.Z),
                    // new Point3D(locPoint.X, locPoint.Y, locPoint.Z),
                    // new Point3D(locPoint.X, locPoint.Y, locPoint.Z + heightVector.Z),
                    // new Point3D(locPoint.X + normalVector.X , locPoint.Y + normalVector.Y, locPoint.Z + heightVector.Z),
                    // new Point3D(locPoint.X + normalVector.X - allignVector.X, locPoint.Y + normalVector.Y - allignVector.Y, locPoint.Z + heightVector.Z),
                    // new Point3D(locPoint.X - allignVector.X, locPoint.Y - allignVector.Y, locPoint.Z + heightVector.Z),
                };

                meshBuilder.AddPolygon(listpoints3D);

                // meshBuilder.AddBox(new Point3D((locPoint.X + normalVector.X - allignVector.X) / 2 , (locPoint.Y + normalVector.Y - allignVector.Y) / 2, (locPoint.Z + normalVector.Z - allignVector.Z + heightVector.Z) / 2), normalVector.X - allignVector.X, normalVector.Y - allignVector.Y, heightVector.Z);

                //meshBuilder.AddPolygonByCuttingEars();

                //meshBuilder.AddLoftedGeometry(new List<IList<Point3D>> { listpoints3D}, new List<IList<Vector3D>> {new List<Vector3D> {heightVector}});
                // meshBuilder.AddBox();

                // Width Vector
                // meshBuilder.AddArrow(new Point3D(x, y, z), new Point3D((double) ((x + mat.Right.X) * item.OverallWidth), y + mat.Right.Y, z + mat.Right.Z), 0.01);
                // meshBuilder.AddArrow(new Point3D(x, y, z), new Point3D((double)((x + mat.Right.X) * item.OverallWidth), y + mat.Right.Y, z + mat.Right.Z), 0.01);

                // var vecHeight = new Vector3D(0, 0, (double) (z + item.OverallHeight) - z);
                // var vecFront = new Vector3D(mat.Forward.X, mat.Forward.Y, 0);
                // var vecWidth = Vector3D.CrossProduct(vecHeight, vecFront);

                var material = new DiffuseMaterial {
                    Brush = Brushes.Aqua
                };
                var myGeometryModel = new GeometryModel3D
                {
                    Material     = material,
                    BackMaterial = material,
                    Geometry     = meshBuilder.ToMesh(true)
                };

                var element = new ModelUIElement3D {
                    Model = myGeometryModel
                };

                control.Viewport3D.Children.Add(element);

                // }
            }

            // Create the floorplan
            // Create FloorPlan
            var walls = xModel.Instances.OfType <IIfcWall>();

            foreach (var wall in walls)
            {
                MeshBuilder meshBuilder = new MeshBuilder(false, false);

                //var points = GeometryHandler.DeriveGeometry2D(wall, context);
                var points = GeometryHandler.GetFootPrint(wall, context);

                meshBuilder.AddPolygon(points);


                var material = new DiffuseMaterial {
                    Brush = Brushes.Red
                };
                var myGeometryModel = new GeometryModel3D
                {
                    Material     = material,
                    BackMaterial = material,
                    Geometry     = meshBuilder.ToMesh(true)
                };

                var element = new ModelUIElement3D {
                    Model = myGeometryModel
                };

                control.Viewport3D.Children.Add(element);
            }
        }
        private void ComboBoxOnSelectionChanged(object sender, SelectionChangedEventArgs selectionChangedEventArgs)
        {
            // INIT THE SIMULATION
            InitSimulation();

            // INTERMEDIATE AREAS FROM ROOMS/SPACES
            var storey = (sender as ComboBox).SelectedItem as IfcBuildingStorey;

            foreach (var space in storey.Spaces)
            {
                // var points = DeriveGeometry(space);
                // var points = DeriveGeometry2D(space);

                var points = CastPoints(GeometryHandler.GetFootPrint(space, context));

                if (points == null)
                {
                    continue;
                }

                sim.layouts[0].scenario.AddArea(space.Name, points, PedSimXMLWriter.areaType.Intermediate);
            }

            // INTERMEDIATE AREAS FROM DOORS
            List <List <point> > doorOpeningElements = new List <List <point> >();

            var doors = xModel.Instances.OfType <IfcRelFillsElement>();

            foreach (var item in doors)
            {
                if (item.RelatedBuildingElement.GetType().ToString().Contains("Door"))
                {
                    var points = CastPoints(GeometryHandler.GetFootPrint(item.RelatingOpeningElement, context));
                    // var points = DeriveGeometry2D(item.RelatingOpeningElement);
                    if (points == null)
                    {
                        continue;
                    }
                    doorOpeningElements.Add(points);
                    sim.layouts[0].scenario.AddArea(item.Name, points, PedSimXMLWriter.areaType.Intermediate);
                }
            }

            // COMPUTE THE ORIGIN AREAS FOR EACH ROOM/SPACE
            // foreach (var space in storey.Spaces)
            // {
            //     var points = DeriveGeometry2D(space);
            // }

            // Get the openings ...
            // List<IfcProduct> doors = new List<IfcProduct>();
            // List<List<point>> doorPolygons = new List<List<point>>();
            // foreach (var item in storey.ContainsElements.ElementAt(0).RelatedElements)
            // {
            //     if (item.GetType().ToString().Contains(@"Door"))
            //     {
            //         // var relVoids = xModel.Instances.OfType<IfcRelFillsElement>();
            //         // foreach (var relVoid in relVoids)
            //         // {
            //         //     if (relVoid.RelatedBuildingElement == item)
            //         //     {
            //         //         var points = DeriveGeometry(relVoid.RelatingOpeningElement);
            //         //         sim.layouts[0].scenario.AddArea(relVoid.RelatingOpeningElement.Name, points, PedSimXMLWriter.areaType.Intermediate);
            //         //     }
            //         // }
            //         // (item as IfcDoor).FillsVoids.
            //         doors.Add(item);
            //     }
            // }
            // foreach (var door in doors)
            // {
            //     var points = DeriveGeometry(door);
            //     doorPolygons.Add(points);
            //     sim.layouts[0].scenario.AddArea(door.Name, points, PedSimXMLWriter.areaType.Intermediate);
            // }

            // GET THE COLUMNS AS OBSTACLES
            // List<IfcProduct> columns = new List<IfcProduct>();
            //
            // foreach (var item in storey.ContainsElements.ElementAt(0).RelatedElements)
            // {
            //     if (item.GetType().ToString().Contains("Column"))
            //     {
            //         columns.Add(item);
            //     }
            // }

            // foreach (var column in columns)
            // {
            //     var columnPoints = DeriveGeometry2D(column);
            //     sim.layouts[0].scenario.AddSolidObstacle(column.Name, columnPoints);
            // }

            // GET THE WALLS AS OBSTACLES
            List <IfcProduct> walls = new List <IfcProduct>();

            foreach (var item in storey.ContainsElements.ElementAt(0).RelatedElements)
            {
                if (item.GetType().ToString().Contains("Wall"))
                {
                    walls.Add(item);
                }
            }

            foreach (var wall in walls)
            {
                // var wallPoints = DeriveGeometry2D(wall);
                var wallPoints = CastPoints(GeometryHandler.GetFootPrint(wall, context));
                // Clipping - Walls are clipped by openings
                int multiplyFactor = 90;

                // WallPolygon
                List <List <IntPoint> > subj = new List <List <IntPoint> >();
                subj.Add(new List <IntPoint>());

                foreach (var item in wallPoints)
                {
                    subj[0].Add(new IntPoint((long)(item.x * multiplyFactor), (long)(item.y * multiplyFactor)));
                }
                // subj[0].Distinct();

                // Clipping Opening Area from doors
                List <List <IntPoint> > clip = new List <List <IntPoint> >();
                int i = 0;
                foreach (var opening in doorOpeningElements)
                {
                    clip.Add(new List <IntPoint>());
                    foreach (var item in opening)
                    {
                        clip[i].Add(new IntPoint((long)(item.x * multiplyFactor), (long)(item.y * multiplyFactor)));
                    }
                    i++;
                }

                var solution = new List <List <IntPoint> >();
                var c        = new Clipper();
                // c.ReverseSolution = true;

                c.AddPolygons(subj, PolyType.ptSubject);
                c.AddPolygons(clip, PolyType.ptClip);

                c.Execute(ClipType.ctDifference, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

                foreach (var solutionItem in solution)
                {
                    List <point> sol = new List <point>();
                    foreach (var coord in  solutionItem)
                    {
                        sol.Add(new point {
                            x = ((double)coord.X) / multiplyFactor, y = ((double)coord.Y) / multiplyFactor
                        });
                    }

                    var convexSol = CreateConvexHull(sol);

                    sim.layouts[0].scenario.AddSolidObstacle(wall.Name, convexSol);
                }
                if (solution.Count == 0)
                {
                    sim.layouts[0].scenario.AddSolidObstacle(wall.Name, wallPoints);
                }
            }

            // SET MIN & MAX
            sim.layouts[0].scenario.maxX = MaxX;
            sim.layouts[0].scenario.minX = MinX;
            sim.layouts[0].scenario.maxY = MaxY;
            sim.layouts[0].scenario.minY = MinY;

            // SERIALIZE
            SerializeSimulation();
        }