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);
            }
        }
Пример #2
0
        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 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);
                }
            }
        }