private static bool IsAccessPoint(Polyline acPline, int index) { Document acDoc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument; Database acCurrDb = acDoc.Database; Editor acEditor = acDoc.Editor; try { DBDictionary outlineExtDict = JPPUtils.getOutlineExtensionDictionary(acPline); // Retrieve the Xrecord ResultBuffer rbLevel = JPPUtils.getXrecord(outlineExtDict.Id, "Vertex_" + index.ToString()); TypedValue[] xrecData = rbLevel.AsArray(); if (xrecData[1].Value.ToString() == "Access_Point") { return(true); } else { return(false); } } catch (Autodesk.AutoCAD.Runtime.Exception acException) { Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog ("The following exception was caught: \n" + acException.Message + "\nError checking for access point\n"); return(true); } }
public static bool EditFFLValue(ObjectId fflToEditId, double level) { Document acDoc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument; Database acCurrDb = acDoc.Database; Editor acEditor = acDoc.Editor; using (Transaction acTrans = acCurrDb.TransactionManager.StartTransaction()) { try { // Prompt user for new FFL double?newFFL = 0.0; // Declare here to ensure in scope for later BlockTable acBlkTbl = acTrans.GetObject(acCurrDb.BlockTableId, OpenMode.ForRead) as BlockTable; BlockReference fflBlock = acTrans.GetObject(fflToEditId, OpenMode.ForRead) as BlockReference; BlockTableRecord acBlkTblRec = acTrans.GetObject(acBlkTbl[fflBlock.Name], OpenMode.ForWrite) as BlockTableRecord; if (acBlkTblRec == null) { acEditor.WriteMessage("\nError FFL block not found."); return(false); } // Check there is only one instance of this block reference in the drawing if (acBlkTblRec.GetBlockReferenceIds(false, true).Count != 1) { acEditor.WriteMessage("\nError more than one instance of the block reference."); return(false); } // Iterate around the object collection to find the polyline to retrieve the current FFL value newFFL = level; double?fflDiff = 0.0; foreach (ObjectId objId in acBlkTblRec) { // Fetch the object Object fflObj = acTrans.GetObject(objId, OpenMode.ForWrite); double?currFFL = 0.0; if (fflObj.GetType() == typeof(Polyline)) { Polyline acPline = fflObj as Polyline; // Check the outline has an extension dictionary DBDictionary acExtDict = (DBDictionary)acTrans.GetObject(acPline.ExtensionDictionary, OpenMode.ForRead); if (acExtDict == null) { acEditor.WriteMessage("\nError cannot retrieve the extension dictionary of polyline."); return(false); } currFFL = JPPUtils.getFFL(acPline.Id); if (currFFL == null) { acEditor.WriteMessage("\nError retrieving current FFL value."); return(false); } fflDiff = newFFL - currFFL; // Update FFL Xrecord ResultBuffer resBuff = new ResultBuffer(); resBuff.Add(new TypedValue((int)DxfCode.ExtendedDataReal, newFFL)); // Overwrite the Xrecord with new data if (!JPPUtils.addXrecord(objId, "FFL", resBuff)) { acEditor.WriteMessage("\nError updating Xrecord with new FFL value."); return(false); } // Update the levels Xrecords to reflect the new ffl for (int vertexIndex = 0; vertexIndex < acPline.NumberOfVertices; vertexIndex++) { // Access Xrecord for the vertex and update the level value ObjectId vertexXrecId = acExtDict.GetAt("Vertex_" + vertexIndex.ToString()); if (vertexXrecId == null) { acEditor.WriteMessage("\nError cannot retrieve vertex Xrecord"); acTrans.Abort(); return(false); } Xrecord vertexXrec = acTrans.GetObject(vertexXrecId, OpenMode.ForWrite) as Xrecord; TypedValue[] vertexXrecData = vertexXrec.Data.AsArray(); // Get the current level double currLevel = Convert.ToDouble(vertexXrecData[3].Value); ResultBuffer newXrecData = new ResultBuffer(); newXrecData.Add(vertexXrecData[0]); newXrecData.Add(vertexXrecData[1]); newXrecData.Add(vertexXrecData[2]); newXrecData.Add(new TypedValue((int)DxfCode.ExtendedDataReal, currLevel + fflDiff)); // Overwrite the data in the Xrecord with new data vertexXrec.Data = newXrecData; } break; } } // Iterate around the MText objects of the block to update the FFL text and // levels text foreach (ObjectId objId in acBlkTblRec) { // Fetch the object Object fflObj = acTrans.GetObject(objId, OpenMode.ForWrite); if (fflObj.GetType() == typeof(MText)) { MText fflMText = (MText)fflObj; if (fflMText.Text.StartsWith("FFL")) { double dblNewFFL = (double)newFFL; fflMText.Contents = "FFL " + dblNewFFL.ToString("N3"); } else { double currLevel = Convert.ToDouble(fflMText.Contents); double newLevel = currLevel + (double)fflDiff; fflMText.Contents = newLevel.ToString("N3"); } } } // Update the graphics fflBlock.UpgradeOpen(); fflBlock.RecordGraphicsModified(true); acTrans.Commit(); return(true); } catch (Autodesk.AutoCAD.Runtime.Exception acException) { Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog ("The following exception was caught: \n" + acException.Message + "\nError editing FFL value!\n"); return(false); } } // return true; }
private static bool Brickwork(bool exposed, ObjectId fflBlockId) { Document acDoc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument; Database acCurrDb = acDoc.Database; Editor acEditor = acDoc.Editor; // Find the outline polyline object Polyline outline = FetchOutline(fflBlockId); if (outline == null) { acEditor.WriteMessage("\nError, unable to retrieve FFL Block ID!"); return(false); } // Retrieve the extension dictionary for the outline DBDictionary blockOutlineExtDict = JPPUtils.getOutlineExtensionDictionary(outline); if (blockOutlineExtDict == null) { acEditor.WriteMessage("\nError, unable to retrieve extension dictionary of outline!"); return(false); } // Retrieve the level at each vertex from the Xrecords in the outline extenstion dictionary double[] levels = new double[outline.NumberOfVertices]; // Array to store the levels for (int index = 0; index < outline.NumberOfVertices; index++) { ResultBuffer rbLevel = JPPUtils.getXrecord(blockOutlineExtDict.Id, "Vertex_" + index.ToString()); TypedValue[] xrecData = rbLevel.AsArray(); levels[index] = Convert.ToDouble(xrecData[3].Value); } // Retrieve the FFL ResultBuffer rbFFL = JPPUtils.getXrecord(blockOutlineExtDict.Id, "FFL"); double FFL = Convert.ToDouble(rbFFL.AsArray()[0].Value); // Create the offset polyline DBObjectCollection offsetOutlineObjects = outline.GetOffsetCurves(0.300); if ((offsetOutlineObjects.Count != 1) || (offsetOutlineObjects[0].GetType() != typeof(Polyline))) { acEditor.WriteMessage("\nError, unable to create offset outline!"); return(false); } Polyline offsetOutline = offsetOutlineObjects[0] as Polyline; // For each vertex of the outline polyline check the level against the FFL. If it is // less the FFL - 0.15 then there is exposed brickwork, if it is greater than FFL - 0.015 // tanking is required. // At the first occurence the coordinates of the previous vertex need to be saved double threshold = FFL - 0.15; int startVertex = 0; // Check if the level of vertex 0 is above of below threshold. If it is iterate anticlockwise // around the outline until a vertex with a level at the threshold is found. This // defines the start point to work round the outline. if ((levels[startVertex] < threshold) || (levels[startVertex] > FFL)) { for (int index = outline.NumberOfVertices - 1; index >= 0; index--) { if ((levels[index] > threshold) || (levels[index] < threshold)) { // Found the start point for this run of exposed or tanked brickwork startVertex = index; break; } } } Point2dCollection hatchBoundaryPoints = new Point2dCollection(); Point2dCollection offsetVertices = new Point2dCollection(); List <int> cornerTextIndex = new List <int>(); bool creatingHatchBoundary = false; for (int index = 0; index < outline.NumberOfVertices; index++) { int vertexIndex; if (index < (outline.NumberOfVertices - startVertex)) { vertexIndex = index + startVertex; } else { vertexIndex = index - (outline.NumberOfVertices - startVertex); } if ((exposed && levels[vertexIndex] < threshold) || (!exposed && (!IsAccessPoint(outline, vertexIndex)) && levels[vertexIndex] > threshold)) { if (hatchBoundaryPoints.Count == 0) // First vertex above or below the threshold { // First point of the hatch boundary will be the previous vertex. // Also, check to see if vertex is an access point. If it is then the hatch boundary point needs to be moved // to accommodate this. It is assumed the access point will be 900mm wide. Point2d firstVertex = new Point2d(); if (vertexIndex == 0) { firstVertex = CheckForAccessPoint(outline, outline.NumberOfVertices - 1, true); } else { firstVertex = CheckForAccessPoint(outline, vertexIndex - 1, true); } hatchBoundaryPoints.Add(firstVertex); creatingHatchBoundary = true; } hatchBoundaryPoints.Add(outline.GetPoint2dAt(vertexIndex)); offsetVertices.Add(offsetOutline.GetPoint2dAt(vertexIndex)); // Check if this vertex is a corner by comparing the angle of the 1st vector and 2nd vector if (IsCorner(outline, vertexIndex)) { cornerTextIndex.Add(vertexIndex); cornerTextIndex.Add(Convert.ToInt32(Math.Ceiling((threshold - levels[vertexIndex]) / 0.075))); } } else if (creatingHatchBoundary) // At the end of an exposed brickwork run { Point2d lastVertex = CheckForAccessPoint(outline, vertexIndex, false); hatchBoundaryPoints.Add(lastVertex); // offsetVertices.Add(offsetPLine.GetPoint2dAt(vertexIndex)); // Now need to close the hatch boundary for (int index2 = offsetVertices.Count - 1; index2 >= 0; index2--) { hatchBoundaryPoints.Add(offsetVertices[index2]); } // Call the function to add the hatch if (!AddHatch(hatchBoundaryPoints, fflBlockId, exposed)) { acEditor.WriteMessage("\nError, unable to exposed brick or tanking hatch!"); return(false); } // Call function to add text if (!AddCourseText(cornerTextIndex, offsetOutline, fflBlockId, exposed)) { acEditor.WriteMessage("\nError, unable to exposed brick or tanking text!"); return(false); } hatchBoundaryPoints.Clear(); offsetVertices.Clear(); cornerTextIndex.Clear(); creatingHatchBoundary = false; } } return(true); }
private static Point2d CheckForAccessPoint(Polyline acPline, int index, bool atStart) { Document acDoc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument; Database acCurrDb = acDoc.Database; Editor acEditor = acDoc.Editor; int nextVertexIndex = 0; int previousVertexIndex = 0; Point2d newPoint = new Point2d(); try { // This function determines whether the point passed to the function is an access point; if it // is then an offset to allow for the access point opening is calculated and the offset point coordinates // returned. The direction of the offset is applied in depends on whether this is the start or end // of the hatch boundary. // If it's the start of the hatch boundary the offset is applied in the direction of the vector from // this point to the next vertex. // If it's the end of the hatch boundary the offset is applied in the direction of a vector from this // to the previous point. // First check if point is an access point as there's nothing to do if not. // Fetch the extension dictionary DBDictionary outlineExtDict = JPPUtils.getOutlineExtensionDictionary(acPline); // Retrieve the Xrecord ResultBuffer rbLevel = JPPUtils.getXrecord(outlineExtDict.Id, "Vertex_" + index.ToString()); TypedValue[] xrecData = rbLevel.AsArray(); if (xrecData[1].Value.ToString() != "Access_Point") { return(newPoint = acPline.GetPoint2dAt(index)); } // First check if the point is the first vertex of the outline previous or next vertex index. if (atStart) { if (index == acPline.NumberOfVertices - 1) { nextVertexIndex = 0; } else { nextVertexIndex = index + 1; } // Calculate new point based on the vector angle double vectorAngle = acPline.GetPoint2dAt(index).GetVectorTo(acPline.GetPoint2dAt(nextVertexIndex)).Angle; newPoint = new Point2d(acPline.GetPoint2dAt(index).X + (Constants.Access_Point_Width / 2) * Math.Cos(vectorAngle), acPline.GetPoint2dAt(index).Y + (Constants.Access_Point_Width / 2) * Math.Sin(vectorAngle)); } else { if (index == 0) { previousVertexIndex = acPline.NumberOfVertices - 1; } else { previousVertexIndex = index - 1; } // Calculate new point based on the vector angle double vectorAngle = acPline.GetPoint2dAt(previousVertexIndex).GetVectorTo(acPline.GetPoint2dAt(index)).Angle; newPoint = new Point2d(acPline.GetPoint2dAt(index).X - (Constants.Access_Point_Width / 2) * Math.Cos(vectorAngle), acPline.GetPoint2dAt(index).Y - (Constants.Access_Point_Width / 2) * Math.Sin(vectorAngle)); } } catch (Autodesk.AutoCAD.Runtime.Exception acException) { Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog ("The following exception was caught: \n" + acException.Message + "\nError accessing vertex Xrecord\n"); newPoint = acPline.GetPoint2dAt(index); } return(newPoint); }
public static bool AddFFLData(ObjectId outlineId) { Document acDoc = Application.DocumentManager.MdiActiveDocument; Editor acEditor = acDoc.Editor; // Each building outline will have an extension dictionary which contains the following XRecords.... // // FFL: Name - "FFL" // Data - double FFL // // Rotation: Name - "Rotation" // Data - double rotation_angle // // Vertex: Name - "Vertex_X", where X is the index // Data - integer Index // Data - string "Corner" or "Access" // Data - string "At_FFL" or "At_150_Down" or "Defined_Level" // Data - double Level // // Add an extension dictionary to the outline // if (!JPPUtils.addExtensionDictionary(outlineId)) { return(false); } double FFLDouble; // Declare here to ensure in scope for later PromptDoubleResult promptFFLDouble = acEditor.GetDouble("\nEnter the FFL: "); if (promptFFLDouble.Status == PromptStatus.OK) { FFLDouble = promptFFLDouble.Value; ResultBuffer xrecFFLData = new ResultBuffer(); xrecFFLData.Add(new TypedValue((int)DxfCode.ExtendedDataReal, FFLDouble)); if (!JPPUtils.addXrecord(outlineId, "FFL", xrecFFLData)) { acEditor.WriteMessage("\nError: could not add Xrecord: FFL."); return(false); } // The rotation will be used as the basis for placing the FFL text. Fetch the angle // of the first vector to the x-axis and create a Xrecord to store it ResultBuffer xrecAngleData = new ResultBuffer(); double? angleOfFirstSegment = getAngle(outlineId); if (angleOfFirstSegment == null) { return(false); } xrecAngleData.Add(new TypedValue((int)DxfCode.ExtendedDataReal, angleOfFirstSegment)); if (!JPPUtils.addXrecord(outlineId, "Rotation", xrecAngleData)) { acEditor.WriteMessage("\nError: could not add Xrecord: Rotation."); return(false); } // Add the corner points XRecords int?NoOfVertices = getNoOfVertices(outlineId); if (NoOfVertices == null) { return(false); } for (int index = 0; index < NoOfVertices; index++) { string xrecName = "Vertex_" + index.ToString(); ResultBuffer xrecVertexData = new ResultBuffer(); xrecVertexData.Add(new TypedValue((int)DxfCode.ExtendedDataInteger16, index)); xrecVertexData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "Corner")); xrecVertexData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "Defined_Level")); // Add the default level at 150mm below FFL xrecVertexData.Add(new TypedValue((int)DxfCode.ExtendedDataReal, (FFLDouble - 0.15))); if (!JPPUtils.addXrecord(outlineId, xrecName, xrecVertexData)) { acEditor.WriteMessage("\nError: could not add Xrecord: Vertex_" + index + "."); return(false); } } return(true); } else if (promptFFLDouble.Status == PromptStatus.Cancel) { acEditor.WriteMessage("\nDefine FFL request cancelled."); return(false); } else { acEditor.WriteMessage("\nError entering FFL."); return(false); } }
public static bool NewFFL() { // Add comment here to explain what the following code does ObjectId outlineId = CreateOutline(); if (outlineId == ObjectId.Null) { return(false); } if (!FormatOutline(outlineId)) { // Remove the outline from the drawing JPPUtils.EraseEntity(outlineId); return(false); } if (!AddFFLData(outlineId)) { // Remove the outline from the drawing JPPUtils.EraseEntity(outlineId); return(false); } if (!AddLevels(outlineId)) { // Remove the outline from the drawing JPPUtils.EraseEntity(outlineId); return(false); } // Adding the text will add other entities to the polyline so need to create an ObjectId collection // to store the object ids of each entity added to enable them to be grouped together. ObjectIdCollection FFLObjectIdCollection = JPPUtils.createObjectIdCollection(outlineId); if (FFLObjectIdCollection == null) { // Remove the outline from the drawing JPPUtils.EraseEntity(outlineId); return(false); } if (!AddText(outlineId, FFLObjectIdCollection)) { // If the text is not added sucessfully need to delete the objects in the object id collection. JPPUtils.EraseObjectsCollection(FFLObjectIdCollection); JPPUtils.EraseEntity(outlineId); return(false); } if (!JPPUtils.CreateNewBlock(FFLObjectIdCollection)) { // If the block is not created need to delete the objects in the object id collection, // and then delete the objects in the object id collection JPPUtils.EraseObjectsCollection(FFLObjectIdCollection); JPPUtils.EraseEntity(outlineId); return(false); } /* if (!JPPUtils.CreateNewGroup(FFLObjectIdCollection)) * { * // If the group is not created need to delete the objects in the object id collection, * // and then delete the objects in the object id collection * return false; * } */ return(true); }
private static bool addAccessPoint(Point3d accessPoint, ObjectId dbObjectId, string level) { Document acDoc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument; Database acCurrDb = acDoc.Database; Editor acEditor = acDoc.Editor; using (Transaction acTrans = acCurrDb.TransactionManager.StartTransaction()) { // Add the access point to the 'buildingOutline' polyline by iterating around the polyline // comparing the distance of each vertex from the start point to the distance of new // point form the start point. When the new point distance is less than the current // vertex add the new point. // // NOTE: this requires that the newpoint lies on the 'buildingOutline' polyline. // try { int accessPointIndex = 0; // Fetch the polyline Polyline buildingOutline = acTrans.GetObject(dbObjectId, OpenMode.ForWrite) as Polyline; for (int index = 0; index <= buildingOutline.NumberOfVertices; index++) { // Check whether index is equal to the number of vertices. If it is the access // point is lies on the segment from the last point of the building outline to the // first point of the building outline so compare the distance to the new point against // the length of the building outline if (index == buildingOutline.NumberOfVertices) { if (buildingOutline.GetDistAtPoint(accessPoint) < buildingOutline.Length) { buildingOutline.AddVertexAt(index, new Point2d(accessPoint.X, accessPoint.Y), 0, 0, 0); accessPointIndex = index; break; // Make sure loop is not executed again } else { // Error condition } } // Else check distance along polyline of new point against each vertex (corner) to find // segment of outline where access point lies. else { if (buildingOutline.GetDistAtPoint(accessPoint) < buildingOutline.GetDistAtPoint(buildingOutline.GetPoint3dAt(index))) { buildingOutline.AddVertexAt(index, new Point2d(accessPoint.X, accessPoint.Y), 0, 0, 0); accessPointIndex = index; break; // Found segment to add } } } // SHOULD add a check in the above to trap case where the added point is a corner. Check with JPP on how to handle this. // Now have the index of the new vertex so update the Xrecord name for each vertex beyond the added // vertex before adding Xrecord for new vertex. First check that new vertex doesn't lie between the // first and last vertices // if (accessPointIndex < buildingOutline.NumberOfVertices - 2) // Not the last vertex if (accessPointIndex < buildingOutline.NumberOfVertices - 1) // Not the last vertex { // Update name Xrecords for those beyond the new vertex for (int index = buildingOutline.NumberOfVertices - 1; index > accessPointIndex; index--) { string newKey = "Vertex_" + index.ToString(); string oldKey = "Vertex_" + (index - 1).ToString(); bool accessPointAdded = JPPUtils.renameXrecord(dbObjectId, oldKey, newKey, true); } } // Fetch the FFL double to calculte value of level // Add the new Xrecord ResultBuffer xrecVertexData = new ResultBuffer(); xrecVertexData.Add(new TypedValue((int)DxfCode.ExtendedDataInteger16, accessPointIndex)); xrecVertexData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "Access_Point")); xrecVertexData.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, level)); // Need to calculate the actual level and therefore need the FFL double?FFLDouble = JPPUtils.getFFL(dbObjectId); // Add the level based on the FFL and whether the access point is at FFL or 150mm below FFL if (level == "At_FFL") { xrecVertexData.Add(new TypedValue((int)DxfCode.ExtendedDataReal, FFLDouble)); } else { xrecVertexData.Add(new TypedValue((int)DxfCode.ExtendedDataReal, (FFLDouble - 0.15))); } bool success = JPPUtils.addXrecord(dbObjectId, ("Vertex_" + accessPointIndex.ToString()), xrecVertexData); acTrans.Commit(); return(true); } catch (Autodesk.AutoCAD.Runtime.Exception acException) { Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog ("The following exception was caught: \n" + acException.Message + "\nError adding access point!\n"); acTrans.Commit(); return(false); } } }