/// <summary> /// Helper method for adding wall segments to ensure everything gets linked correctly. /// </summary> private void AddWallSegment(WallSegment newSegment) { Segments.Add(newSegment); bool startFound = false; bool endFound = false; foreach (WallJoint wj in Joints) { if (wj.Point.IsEqualTo(newSegment.StartPoint)) { startFound = true; newSegment.StartJoint = wj; wj.AddWallSegment(newSegment); } if (wj.Point.IsEqualTo(newSegment.EndPoint)) { endFound = true; newSegment.EndJoint = wj; wj.AddWallSegment(newSegment); } } if (!startFound) { WallJoint newWj = new WallJoint(); newWj.Point = newSegment.StartPoint; newSegment.StartJoint = newWj; newWj.AddWallSegment(newSegment); newWj.Type = JointType.Internal; if (AccessLookup.ContainsKey(newWj.Point)) { newWj.RelativeOffset = AccessLookup[newWj.Point].Offset; newWj.Type = JointType.AccessPoint; } Joints.Add(newWj); } if (!endFound) { WallJoint newWj = new WallJoint(); newWj.Point = newSegment.EndPoint; newSegment.EndJoint = newWj; newWj.AddWallSegment(newSegment); newWj.Type = JointType.Internal; if (AccessLookup.ContainsKey(newWj.Point)) { newWj.RelativeOffset = AccessLookup[newWj.Point].Offset; newWj.Type = JointType.AccessPoint; } Joints.Add(newWj); } newSegment.Generate(); }
private void TraverseExternalSegment(WallSegment currentSegment, WallJoint currentNode, WallJoint startNode) { currentSegment.External = true; PerimeterPath.Add(currentNode); //Get next WallSegment nextSegment = currentNode.NextClockwise(currentSegment); WallJoint nextJoint; if (nextSegment.StartPoint.IsEqualTo(currentNode.Point)) { nextJoint = nextSegment.EndJoint; } else { nextJoint = nextSegment.StartJoint; } if (currentNode.Type == JointType.Internal) { if (Collinear(currentSegment.StartPoint, currentSegment.EndPoint, nextJoint.Point)) { //Check if on line currentNode.Type = JointType.ExternalIntermediate; } else { currentNode.Type = JointType.ExternalCorner; } } if (nextJoint.Point.IsEqualTo(startNode.Point)) { //Back to start nextSegment.External = true; nextJoint.Type = JointType.ExternalCorner; } else { TraverseExternalSegment(nextSegment, nextJoint, startNode); } }
/// <summary> /// Create the plot and establish all drawing objects. Only to be called when plot is first created or to be reset from plot types /// MUST be called from an active transaction /// <exception cref="ArgumentOutOfRangeException"> An ArugmentOutOfRageException is thrown when a matching wall segment in the plot type isnt found or is duplicated </exception> /// </summary> public void Generate() { Status = PlotStatus.ForApproval; StatusMessage = "Plot generated successfully"; Database acCurDb; acCurDb = Application.DocumentManager.MdiActiveDocument.Database; Transaction acTrans = acCurDb.TransactionManager.TopTransaction; BlockTable acBlkTbl; acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord acBlkTblRec; acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; BlockReference newBlockRef; //Link the block reference if (BlockRefPtr == 0) { BlockRef = Core.Utilities.InsertBlock(BasePoint, Rotation, PlotType.BlockID); newBlockRef = (BlockReference)BlockRef.GetObject(OpenMode.ForWrite); } else { //TODO: Add regeneration code. throw new NotImplementedException(); } //Explode the blockref DBObjectCollection explodedBlock = new DBObjectCollection(); newBlockRef.Explode(explodedBlock); //TODO: Move releveant blocks here Main.LoadBlocks(); AccessLookup = new Dictionary <Point3d, AccessPoint>(); foreach (Entity entToAdd in explodedBlock) { //Pull the circles that id access points out if (entToAdd is Circle) { Circle c = entToAdd as Circle; if (c.Layer == Civils.Constants.JPP_HS_PlotPerimiter) { var rb = c.XData; string target = ""; foreach (var tv in rb) { target = tv.Value as string; } Point3d? master = null; AccessPoint?typeAP = null; foreach (AccessPoint ap in this.PlotType.AccessPoints) { //TODO: Add code to match to PlotType WS by comparing start and end points if (ap.Guid == target) { if (master == null) { master = c.Center; typeAP = ap; } else { throw new ArgumentOutOfRangeException("Wall segment match already found", (System.Exception)null); } } } if (master == null) { throw new ArgumentOutOfRangeException("No matching wall segment found", (System.Exception)null); } AccessLookup.Add(master.Value, typeAP.Value); } } } foreach (Entity entToAdd in explodedBlock) { //Identify the lines as these indicate wall segments //TODO: Add handling here for when a line is NOT a wall segmen if (entToAdd is Line) { Line segment = entToAdd as Line; string target = ""; //Get type id var rb = segment.XData; foreach (var tv in rb) { target = tv.Value as string; } WallSegment master = null; WallSegment seg = new WallSegment(); foreach (WallSegment ptWS in this.PlotType.Segments) { //TODO: Add code to match to PlotType WS by comparing start and end points if (ptWS.Guid == target) { if (master == null) { master = ptWS; } else { throw new ArgumentOutOfRangeException("Wall segment match already found", (System.Exception)null); } } } if (master == null) { throw new ArgumentOutOfRangeException("No matching wall segment found", (System.Exception)null); } //TODO: Check, think object is not part of database seg.PerimeterLine = segment.ObjectId; seg.StartPoint = segment.StartPoint; seg.EndPoint = segment.EndPoint; seg.Guid = master.Guid; AddWallSegment(seg); } } //HANDLE EXTERNAL LEVELS //Traverse through wall segments to find external ones, starting with basepoint //Find basepoint WallJoint startNode = null; foreach (WallJoint wj in Joints) { if (wj.Point.IsEqualTo(BasePoint)) { startNode = wj; } } if (startNode == null) { throw new ArgumentOutOfRangeException("Basepoint does not lie on wall joint", (System.Exception)null); } //Recursively traverse through the segments to find the external ones WallSegment startSegment = startNode.North; WallJoint nextNode; if (startSegment.EndPoint == startNode.Point) { nextNode = startSegment.StartJoint; } else { nextNode = startSegment.EndJoint; } PerimeterPath = new List <WallJoint>(); PerimeterPath.Add(startNode); TraverseExternalSegment(startSegment, nextNode, startNode); //Remove the last point PerimeterPath.RemoveAt(PerimeterPath.Count - 1); //GENERATE SUB ELEMENTS foreach (WallJoint wj in PerimeterPath) { wj.Generate(Rotation); } //Check to see if FFL needs to be set if (UpdateLevelsFromSurface) { GetFFLfromSurface(); } Update(); /*Polyline acPline = entToAdd as Polyline; * foreach (AccessPoint ap in PlotType.AccessPoints) * { * PlotLevel pl = new PlotLevel(false, ap.Offset, this, ap.Parameter); * pl.Generate(acPline.GetPointAtParameter(ap.Parameter)); * Level.Add(pl); * } * * //Iterate over all the corners and add to the drawing * int vn = acPline.NumberOfVertices; * for (int i = 0; i < vn; i++) * { * Point3d pt = acPline.GetPoint3dAt(i); * PlotLevel pl = new PlotLevel(false, -0.15, this, acPline.GetParameterAtPoint(pt)); * pl.Generate(pt); * Level.Add(pl); * } * * // Open the Block table for read * BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable; * * // Open the Block table record Model space for write * BlockTableRecord acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; * * //Ad the FFL Label * // Create a multiline text object * using (MText acMText = new MText()) * { * //Find the centre of the plot outline as an estimated point of insertion * Solid3d Solid = new Solid3d(); * DBObjectCollection coll = new DBObjectCollection * { * acPline * }; * Solid.Extrude(((Region)Region.CreateFromCurves(coll)[0]), 1, 0); * Point3d centroid = new Point3d(Solid.MassProperties.Centroid.X, Solid.MassProperties.Centroid.Y, 0); * Solid.Dispose(); * * acMText.Location = centroid; * acMText.Contents = FinishedFloorLevelText; * acMText.Rotation = Rotation; * acMText.Height = 7; * acMText.Attachment = AttachmentPoint.MiddleCenter; * * FFLLabel = acBlkTblRec.AppendEntity(acMText); * acTrans.AddNewlyCreatedDBObject(acMText, true); * } * * GenerateHatching();*/ }