Created
November 25, 2024 16:26
-
-
Save MadhukarMoogala/57be825b2175027411d36bdfc27fe434 to your computer and use it in GitHub Desktop.
Updates the profile curve of an associative planar surface in AutoCAD.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Updates the profile curve of an associative planar surface in AutoCAD. | |
/// Assumes the user has selected a planar surface with a rectangular profile curve. | |
/// Demonstrates the workflow for: | |
/// - Verifying surface associativity | |
/// - Extracting and transforming the profile | |
/// - Updating the surface with a modified profile | |
/// </summary> | |
[CommandMethod("UpdateAssociatePlanarSurface")] | |
public static void UpdateAssociatePlanarSurface() | |
{ | |
// Get the active AutoCAD database | |
Database activeDatabase = HostApplicationServices.WorkingDatabase; | |
// Prompt the user to select a surface | |
PromptEntityOptions surfaceSelectionPrompt = new PromptEntityOptions("\nSelect a surface: "); | |
surfaceSelectionPrompt.SetRejectMessage("Must be a Surface!"); // Reject non-surface entities | |
surfaceSelectionPrompt.AddAllowedClass(typeof(DBSurface), exactMatch: false); | |
Editor documentEditor = Application.DocumentManager.MdiActiveDocument.Editor; | |
PromptEntityResult selectionResult = documentEditor.GetEntity(surfaceSelectionPrompt); | |
// Exit if selection is canceled or invalid | |
if (selectionResult.Status != PromptStatus.OK) | |
return; | |
// Begin a transaction to handle database changes | |
using Transaction transaction = selectionResult.ObjectId.Database.TransactionManager.StartTransaction(); | |
try | |
{ | |
// Access the selected surface | |
DBSurface selectedSurface = transaction.GetObject(selectionResult.ObjectId, OpenMode.ForWrite) as DBSurface; | |
if (selectedSurface == null) | |
return; | |
// Check if the surface is associative by verifying the CreationActionBodyId | |
var surfaceCreationActionId = selectedSurface.CreationActionBodyId; | |
bool isSurfaceAssociative = false; | |
if (surfaceCreationActionId != ObjectId.Null) | |
{ | |
AssocActionBody associatedActionBody = transaction.GetObject(surfaceCreationActionId, OpenMode.ForRead) as AssocActionBody; | |
isSurfaceAssociative = associatedActionBody != null; | |
} | |
if (isSurfaceAssociative) | |
{ | |
// Retrieve the associated action body for the planar surface | |
AssocPlaneSurfaceActionBody planeActionBody = transaction.GetObject(surfaceCreationActionId, OpenMode.ForWrite) as AssocPlaneSurfaceActionBody; | |
// Retrieve the input path parameters for the action body | |
planeActionBody.GetInputPaths(out EdgeRef[][][] edgeReferenceLayers); | |
// List to store extracted entities from edge references | |
var ents = new List<Entity>(); | |
// Extract entities from the nested edge reference layers | |
for (int layerIndex = 0; layerIndex < edgeReferenceLayers.Length; layerIndex++) | |
{ | |
EdgeRef[][] edgeReferenceRows = edgeReferenceLayers[layerIndex]; | |
for (int rowIndex = 0; rowIndex < edgeReferenceRows.Length; rowIndex++) | |
{ | |
EdgeRef[] edgeReferences = edgeReferenceRows[rowIndex]; | |
for (int referenceIndex = 0; referenceIndex < edgeReferences.Length; referenceIndex++) | |
{ | |
// Convert edge references to entities and store them | |
Entity extractedEntity = edgeReferences[referenceIndex].CreateEntity(); | |
extractedEntity.ColorIndex = 1; // Optional: Set the color for visual distinction | |
extractedEntity.SetDatabaseDefaults(); | |
ents.Add(extractedEntity); | |
SubEntityUtilities.PostToDataBase(extractedEntity); // Add the entity to the database | |
} | |
} | |
} | |
// Clone the first extracted profile and apply a transformation | |
var profile = ents[0].Clone() as Entity; | |
if (profile is Polyline pl) | |
{ | |
// Calculate the centroid of the polyline for transformation | |
var center = GetCentroid(pl); | |
// Apply a scaling transformation to the profile | |
profile.TransformBy(Matrix3d.Scaling(10, center)); | |
// Update the input path with the modified profile | |
var edges = new List<EdgeRef> { new EdgeRef(profile) }; | |
planeActionBody.UpdateInputPath(0, new PathRef(edges.ToArray())); | |
} | |
// Reevaluate the associative network to apply the changes | |
AssocManager.EvaluateTopLevelNetwork(activeDatabase, null, 0); | |
} | |
// Commit the transaction to save changes | |
transaction.Commit(); | |
} | |
catch (System.Exception ex) | |
{ | |
// Handle errors and abort the transaction if necessary | |
documentEditor.WriteMessage($"\nError: {ex.Message}"); | |
transaction.Abort(); | |
} | |
} | |
/// <summary> | |
/// Calculates the centroid of a closed polyline. | |
/// Throws an exception if the polyline is not closed. | |
/// </summary> | |
/// <param name="polyline">The closed polyline for which the centroid is calculated.</param> | |
/// <returns>The centroid of the polyline as a Point3d.</returns> | |
public static Point3d GetCentroid(Polyline polyline) | |
{ | |
if (!polyline.Closed) | |
throw new Exception(ErrorStatus.InvalidInput, "Polyline must be closed"); | |
double area = 0, cx = 0, cy = 0; | |
int numVertices = polyline.NumberOfVertices; | |
// Apply the Shoelace formula for centroid and area calculation | |
for (int i = 0; i < numVertices; i++) | |
{ | |
Point2d p1 = polyline.GetPoint2dAt(i); | |
Point2d p2 = polyline.GetPoint2dAt((i + 1) % numVertices); | |
double temp = p1.X * p2.Y - p2.X * p1.Y; | |
area += temp; | |
cx += (p1.X + p2.X) * temp; | |
cy += (p1.Y + p2.Y) * temp; | |
} | |
area *= 0.5; | |
cx /= (6 * area); | |
cy /= (6 * area); | |
// Return the calculated centroid | |
return new Point3d(cx, cy, 0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
AssocFramework.mp4