Example #1
0
        public void GeneratePlan(Point3d location)
        {
            Standard.Apply(this);

            var pLines  = new List <Polyline>();
            var acDoc   = Application.DocumentManager.MdiActiveDocument;
            var acCurDb = acDoc.Database;

            //Sort pipe connections for ease of drawing
            var sortedPipes = IncomingPipes.OrderBy(p => p.Angle).ToList();

            using (var tr = acCurDb.TransactionManager.StartTransaction())
            {
                var offset = location.GetAsVector().Subtract(IntersectionPoint.GetAsVector());

                //Calculate alternate connection point
                Circle   slopeCircle    = new Circle(location, Vector3d.ZAxis, 450);
                Vector3d slopeIntersect = location.GetVectorTo(OutgoingConnection.Location.Add(offset));
                slopeIntersect = slopeIntersect * 450 / slopeIntersect.Length;
                Point2d slopePoint2D = new Point2d(location.Add(slopeIntersect).X, location.Add(slopeIntersect).Y);

                // Open the Block table for read
                BlockTable acBlkTbl;
                acBlkTbl = tr.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;

                // Open the Block table record Model space for write
                BlockTableRecord acBlkTblRec;
                acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

                acCurDb.RegisterLayer(Constants.LAYER_PIPE_WALLS_NAME, Constants.LAYER_PIPE_WALLS_COLOR);
                acCurDb.RegisterLayer(Constants.LAYER_PIPE_CENTRE_LINE_NAME, Constants.LAYER_PIPE_CENTRE_LINE_COLOR, Constants.LAYER_PIPE_CENTRE_LINE_TYPE);
                acCurDb.RegisterLayer(Constants.LAYER_MANHOLE_WALL_NAME, Constants.LAYER_MANHOLE_WALL_COLOR);
                acCurDb.RegisterLayer(Constants.LAYER_MANHOLE_FURNITURE_NAME, Constants.LAYER_MANHOLE_FURNITURE_COLOR);

                Circle pipeIntrusion = new Circle(location, Vector3d.ZAxis, (double)(Diameter / 2) - 150f);

                //Outgoing line
                Polyline outgoingLine = new Polyline();
                outgoingLine.AddVertexAt(0, new Point2d(location.X, location.Y), 0, 0, 0);
                outgoingLine.AddVertexAt(1, new Point2d(OutgoingConnection.Location.Add(offset).X, OutgoingConnection.Location.Add(offset).Y), 0, 0, 0);
                outgoingLine.Layer = Constants.LAYER_PIPE_CENTRE_LINE_NAME;

                Polyline outgoingoffsetPlus = outgoingLine.GetOffsetCurves(OutgoingConnection.Diameter / 2)[0] as Polyline;
                outgoingoffsetPlus.Layer = Constants.LAYER_PIPE_WALLS_NAME;
                Polyline outgoingoffsetMinus = outgoingLine.GetOffsetCurves(-OutgoingConnection.Diameter / 2)[0] as Polyline;
                outgoingoffsetMinus.Layer = Constants.LAYER_PIPE_WALLS_NAME;

                //Add descriptive text
                var outLabel = new MText
                {
                    Location   = new Point3d(OutgoingConnection.Location.Add(offset).X, OutgoingConnection.Location.Add(offset).Y, 0),
                    Contents   = OutgoingConnection.Code + "\\P" + OutgoingConnection.Diameter + "%%C",
                    TextHeight = 40
                };

                outLabel.AlignTo(outgoingLine);
                acBlkTblRec.AppendEntity(outLabel);
                tr.AddNewlyCreatedDBObject(outLabel, true);

                //Pipe walls
                Polyline outouteroffsetPlus = outgoingLine.GetOffsetCurves(OutgoingConnection.Diameter / 2 + 20f)[0] as Polyline;
                outouteroffsetPlus.Layer = Constants.LAYER_PIPE_WALLS_NAME;
                Point3dCollection intersection = new Point3dCollection();
                outouteroffsetPlus.IntersectWith(pipeIntrusion, Intersect.ExtendArgument, intersection, IntPtr.Zero, IntPtr.Zero);
                outouteroffsetPlus.AddVertexAt(0, new Point2d(intersection[0].X, intersection[0].Y), 0, 0, 0);
                outouteroffsetPlus.RemoveVertexAt(1);

                Polyline outouteroffsetMinus = outgoingLine.GetOffsetCurves(-OutgoingConnection.Diameter / 2 - 20f)[0] as Polyline;
                outouteroffsetMinus.Layer = Constants.LAYER_PIPE_WALLS_NAME;
                intersection = new Point3dCollection();
                outouteroffsetMinus.IntersectWith(pipeIntrusion, Intersect.ExtendArgument, intersection, IntPtr.Zero, IntPtr.Zero);
                outouteroffsetMinus.AddVertexAt(0, new Point2d(intersection[0].X, intersection[0].Y), 0, 0, 0);
                outouteroffsetMinus.RemoveVertexAt(1);

                Polyline outcloseWall = new Polyline();
                outcloseWall.AddVertexAt(0, new Point2d(outouteroffsetMinus.StartPoint.X, outouteroffsetMinus.StartPoint.Y), 0, 0, 0);
                outcloseWall.AddVertexAt(0, new Point2d(outouteroffsetPlus.StartPoint.X, outouteroffsetPlus.StartPoint.Y), 0, 0, 0);
                outcloseWall.Layer = Constants.LAYER_PIPE_WALLS_NAME;

                acBlkTblRec.AppendEntity(outgoingLine);
                tr.AddNewlyCreatedDBObject(outgoingLine, true);

                acBlkTblRec.AppendEntity(outouteroffsetMinus);
                tr.AddNewlyCreatedDBObject(outouteroffsetMinus, true);
                acBlkTblRec.AppendEntity(outouteroffsetPlus);
                tr.AddNewlyCreatedDBObject(outouteroffsetPlus, true);
                acBlkTblRec.AppendEntity(outcloseWall);
                tr.AddNewlyCreatedDBObject(outcloseWall, true);

                Polyline lastLine = outgoingoffsetPlus;

                for (int i = 0; i < sortedPipes.Count(); i++)
                {
                    PipeConnection pipeConnection = sortedPipes.ToArray()[i];

                    //Create centreline
                    Polyline newLine = new Polyline();//location, pipeConnection.Location.Add(offset)
                    newLine.AddVertexAt(0, new Point2d(location.X, location.Y), 0, 0, 0);
                    newLine.AddVertexAt(1, new Point2d(pipeConnection.Location.Add(offset).X, pipeConnection.Location.Add(offset).Y), 0, 0, 0);
                    newLine.Layer = Constants.LAYER_PIPE_CENTRE_LINE_NAME;

                    //Add descriptive text
                    var label = new MText
                    {
                        Location = new Point3d(pipeConnection.Location.Add(offset).X, pipeConnection.Location.Add(offset).Y, 0),
                        Contents = pipeConnection.Code + "\\P" + pipeConnection.Diameter + "%%C"
                    };


                    acBlkTblRec.AppendEntity(label);
                    tr.AddNewlyCreatedDBObject(label, true);

                    label.TextHeight = 40;
                    label.AlignTo(newLine);

                    //Pipe walls
                    Polyline outeroffsetPlus = newLine.GetOffsetCurves(pipeConnection.Diameter / 2 + 20f)[0] as Polyline;
                    outeroffsetPlus.Layer = Constants.LAYER_PIPE_WALLS_NAME;
                    intersection          = new Point3dCollection();
                    outeroffsetPlus.IntersectWith(pipeIntrusion, Intersect.ExtendArgument, intersection, IntPtr.Zero, IntPtr.Zero);
                    outeroffsetPlus.AddVertexAt(0, new Point2d(intersection[0].X, intersection[0].Y), 0, 0, 0);
                    outeroffsetPlus.RemoveVertexAt(1);

                    Polyline outeroffsetMinus = newLine.GetOffsetCurves(-pipeConnection.Diameter / 2 - 20f)[0] as Polyline;
                    outeroffsetMinus.Layer = Constants.LAYER_PIPE_WALLS_NAME;
                    intersection           = new Point3dCollection();
                    outeroffsetMinus.IntersectWith(pipeIntrusion, Intersect.ExtendArgument, intersection, IntPtr.Zero, IntPtr.Zero);
                    outeroffsetMinus.AddVertexAt(0, new Point2d(intersection[0].X, intersection[0].Y), 0, 0, 0);
                    outeroffsetMinus.RemoveVertexAt(1);

                    Polyline closeWall = new Polyline();
                    closeWall.AddVertexAt(0, new Point2d(outeroffsetMinus.StartPoint.X, outeroffsetMinus.StartPoint.Y), 0, 0, 0);
                    closeWall.AddVertexAt(0, new Point2d(outeroffsetPlus.StartPoint.X, outeroffsetPlus.StartPoint.Y), 0, 0, 0);
                    closeWall.Layer = Constants.LAYER_PIPE_WALLS_NAME;


                    //Check that angle is ok
                    //Skip the check if this is the only incoming pipe
                    if (sortedPipes.Count() > 1)
                    {
                        if (pipeConnection.Angle < 135 || pipeConnection.Angle > 225)
                        {
                            //Angle exceeds 45° so change
                            Point3dCollection slopeIntersectCollection = new Point3dCollection();
                            newLine.IntersectWith(slopeCircle, Intersect.ExtendArgument, slopeIntersectCollection, IntPtr.Zero, IntPtr.Zero);
                            Point3d circleIntersectPoint = slopeIntersectCollection[0];
                            newLine.AddVertexAt(1, new Point2d(circleIntersectPoint.X, circleIntersectPoint.Y), 0, 0, 0);

                            newLine.SetPointAt(0, slopePoint2D);
                        }
                    }

                    Polyline offsetPlus = newLine.GetOffsetCurves(pipeConnection.Diameter / 2)[0] as Polyline;
                    offsetPlus.Layer = Constants.LAYER_PIPE_WALLS_NAME;
                    Polyline offsetMinus = newLine.GetOffsetCurves(-pipeConnection.Diameter / 2)[0] as Polyline;
                    offsetMinus.Layer = Constants.LAYER_PIPE_WALLS_NAME;

                    //Fillet
                    Point3dCollection collection = new Point3dCollection();
                    offsetMinus.IntersectWith(lastLine, Intersect.ExtendBoth, collection, IntPtr.Zero, IntPtr.Zero);

                    //Check that the lines do intersect, may not if small pipe to large when parallel
                    if (collection.Count > 0)
                    {
                        var inter = collection[0];
                        lastLine.SetPointAt(0, new Point2d(inter.X, inter.Y));
                        offsetMinus.SetPointAt(0, new Point2d(inter.X, inter.Y));
                    }

                    acBlkTblRec.AppendEntity(newLine);
                    tr.AddNewlyCreatedDBObject(newLine, true);

                    lastLine.JoinEntity(offsetMinus);
                    pLines.Add(lastLine);

                    acBlkTblRec.AppendEntity(outeroffsetMinus);
                    tr.AddNewlyCreatedDBObject(outeroffsetMinus, true);
                    acBlkTblRec.AppendEntity(outeroffsetPlus);
                    tr.AddNewlyCreatedDBObject(outeroffsetPlus, true);

                    acBlkTblRec.AppendEntity(closeWall);
                    tr.AddNewlyCreatedDBObject(closeWall, true);

                    lastLine = offsetPlus;
                }

                Point3dCollection lastCollection = new Point3dCollection();
                outgoingoffsetMinus.IntersectWith(lastLine, Intersect.ExtendBoth, lastCollection, IntPtr.Zero, IntPtr.Zero);

                if (lastCollection.Count > 0)
                {
                    Point3d lastIntersection = lastCollection[0]; //No intersection throwing error???
                    lastLine.SetPointAt(0, new Point2d(lastIntersection.X, lastIntersection.Y));
                    outgoingoffsetMinus.SetPointAt(0, new Point2d(lastIntersection.X, lastIntersection.Y));
                }

                lastLine.JoinEntity(outgoingoffsetMinus);
                pLines.Add(lastLine);

                foreach (var line in pLines)
                {
                    line.FilletAll();
                    acBlkTblRec.AppendEntity(line);
                    tr.AddNewlyCreatedDBObject(line, true);
                }

                //Create rings
                var innerManhole = new Circle(location, Vector3d.ZAxis, Diameter / 2)
                {
                    Layer = Constants.LAYER_MANHOLE_WALL_NAME
                };
                acBlkTblRec.AppendEntity(innerManhole);
                tr.AddNewlyCreatedDBObject(innerManhole, true);

                //Calculate best location for steps and check minimum benching
                double maxAngle   = 0;
                int    maxSegment = 0;

                double minAngle   = double.MaxValue;
                int    minSegment = 0;

                double previousAngle = 0;
                for (int i = 0; i < sortedPipes.Count(); i++)
                {
                    PipeConnection pc = sortedPipes.ToArray()[i];

                    double anglebetween = pc.Angle - previousAngle;
                    previousAngle += pc.Angle;

                    if (anglebetween > maxAngle)
                    {
                        maxAngle   = anglebetween;
                        maxSegment = i;
                    }

                    if (anglebetween < maxAngle)
                    {
                        maxAngle   = anglebetween;
                        maxSegment = i;
                    }
                }

                PipeConnection edgeSegment = sortedPipes.ToArray()[maxSegment];
                double         stepCenter  = edgeSegment.Angle - maxAngle / 2;

                //check the last segment is not better
                PipeConnection endSegment = sortedPipes.ToArray().Last();
                double         lastAngle  = 360 - endSegment.Angle;
                if (lastAngle > maxAngle)
                {
                    stepCenter = 360 - lastAngle / 2;
                }

                Polyline stepCenterLine = new Polyline();
                stepCenterLine.AddVertexAt(0, new Point2d(outgoingLine.StartPoint.X, outgoingLine.StartPoint.Y), 0, 0, 0);
                stepCenterLine.AddVertexAt(1, new Point2d(outgoingLine.EndPoint.X, outgoingLine.EndPoint.Y), 0, 0, 0);

                Matrix3d           curUCSMatrix = acDoc.Editor.CurrentUserCoordinateSystem;
                CoordinateSystem3d curUCS       = curUCSMatrix.CoordinateSystem3d;

                // Rotate the polyline 45 degrees, around the Z-axis of the current UCS
                // using a base point of (4,4.25,0)
                stepCenterLine.TransformBy(Matrix3d.Rotation(stepCenter * Math.PI / 180, -curUCS.Zaxis, stepCenterLine.StartPoint));

                /*acBlkTblRec.AppendEntity(stepCenterLine);
                 * tr.AddNewlyCreatedDBObject(stepCenterLine, true);*/


                //TODO: Needs reviewing - as it need to be kept?
                //TODO: Make sure this works and allow for pipe widths not centre lines

                /*//Calculate both intersection points
                 * (Vector3d majorBenching, Vector3d minorBenching) = CalculateBenching(stepCenterLine, innerManhole);
                 *
                 *
                 * if (minorBenching.Length < MinimumMinorBenching)
                 * {
                 *  Vector3d adjustment = minorBenching * (MinimumMinorBenching / minorBenching.Length);
                 *  innerManhole.Center = innerManhole.Center.Add(adjustment);
                 *  (majorBenching, minorBenching) = CalculateBenching(stepCenterLine, innerManhole);
                 * }
                 *
                 * if (majorBenching.Length < MinimumMajorBenching)
                 * {
                 *  if (minorBenching.Length > MinimumMinorBenching)
                 *  {
                 *      Vector3d adjustment = minorBenching * (MinimumMinorBenching / minorBenching.Length);
                 *      innerManhole.Center = innerManhole.Center.Add(adjustment);
                 *      (majorBenching, minorBenching) = CalculateBenching(stepCenterLine, innerManhole);
                 *
                 *      if (majorBenching.Length < MinimumMajorBenching)
                 *      {
                 *          throw new ArgumentException("Major benching does not meet minimum distances");
                 *      }
                 *  }
                 *
                 *  throw new ArgumentException("Major benching does not meet minimum distances");
                 * }*/

                //Create rings now offset is fixed
                var outerManhole = new Circle(location, Vector3d.ZAxis, Diameter / 2 + WallThickness)
                {
                    Layer = Constants.LAYER_MANHOLE_WALL_NAME
                };
                acBlkTblRec.AppendEntity(outerManhole);
                tr.AddNewlyCreatedDBObject(outerManhole, true);

                var outerSurround = new Circle(location, Vector3d.ZAxis, Diameter / 2 + WallThickness + 100f)
                {
                    Layer = Constants.LAYER_MANHOLE_WALL_NAME
                };
                acBlkTblRec.AppendEntity(outerSurround);
                tr.AddNewlyCreatedDBObject(outerSurround, true);


                //Generate manhole cover
                var cover = GenerateManholeCover(stepCenterLine, innerManhole);
                cover.Layer = Constants.LAYER_MANHOLE_FURNITURE_NAME;
                acBlkTblRec.AppendEntity(cover);
                tr.AddNewlyCreatedDBObject(cover, true);

                //Generate manhole step
                var step = GenerateManholeStep(stepCenterLine, innerManhole);
                foreach (var entity in step)
                {
                    entity.Layer = Constants.LAYER_MANHOLE_FURNITURE_NAME;
                    acBlkTblRec.AppendEntity(entity);
                    tr.AddNewlyCreatedDBObject(entity, true);
                }

                //Generate benching
                var bench = GenerateBenching(stepCenterLine, innerManhole, pLines);
                foreach (var entity in bench)
                {
                    entity.Layer = Constants.LAYER_MANHOLE_FURNITURE_NAME;
                    acBlkTblRec.AppendEntity(entity);
                    tr.AddNewlyCreatedDBObject(entity, true);
                }

                //Add safety features
                if (SafetyChain)
                {
                    throw new NotImplementedException();
                }
                if (SafetyRail)
                {
                    throw new NotImplementedException();
                }

                //Generate Table
                var tbLocation = new Point3d(location.X + (1800 * 1.1), location.Y + 450, 0);
                var tb         = GenerateTable(this, tbLocation);
                acBlkTblRec.AppendEntity(tb);
                tr.AddNewlyCreatedDBObject(tb, true);

                var height = outgoingLine.Length * 2;
                var width  = outgoingLine.Length + tb.Width + (tbLocation.X - location.X);
                LayoutHeight = height * SCALE * 1.1;
                LayoutWidth  = width * SCALE * 1.1;
                var shift = (width / 2) - outgoingLine.Length;
                Centre = new Point3d(location.X + shift, location.Y, 0);
                //Finalize
                tr.Commit();
            }
        }