Autocad C Custom Draw Ling
I'm trying to draw a solid 3D shape in AutoCAD programmatically. I can get the shape to draw as a wireframe. Here is what my code currently draws
The object is a bunch of AutoCAD lines grouped together into a Group object. What I want is a method that takes a Group as an argument and turns that group into a solid blockreference. Here is my attempt at it.
public static void DefineBlockFromGroup(Group groupToCreateBlockFrom, string blockName, Point3d origin, bool replaceChosenEntities = false) { List<ObjectId> idsOfEntitiesInGroup = groupToCreateBlockFrom.GetAllEntityIds().ToList(); //Getting the entities that will be used to create the block CreateBlockDefinition(idsOfEntitiesInGroup, blockName, origin, replaceChosenEntities); } public static void CreateBlockDefinition(List<ObjectId> entities, string blockName, Point3d origin, bool replaceChosenEntities = false) { BlockTableRecord record = new BlockTableRecord(); //Will become record of new block type ObjectId blockId = ObjectId.Null; //Will become id of new block type using (Transaction tr = _database.TransactionManager.StartTransaction()) using (DocumentLock docLock = _activeDocument.LockDocument()) { BlockTable bt = (BlockTable)tr.GetObject(_database.BlockTableId, OpenMode.ForRead); //Getting block table to put new record in bt.UpgradeOpen(); record = new BlockTableRecord(); //New record will contain all entities which will make up the block record.Name = blockName; //Setting name of the block record.Origin = origin; //Setting origin point of the block bt.Add(record); tr.AddNewlyCreatedDBObject(record, true); blockId = bt[record.Name]; tr.Commit(); } //copy the select entities to block by using deepclone. ObjectIdCollection collection = new ObjectIdCollection(entities.ToArray()); IdMapping mapping = new IdMapping(); _database.DeepCloneObjects(collection, blockId, mapping, false); if (replaceChosenEntities) { using (Transaction tr = _database.TransactionManager.StartTransaction()) using (DocumentLock docLock = _activeDocument.LockDocument()) { Entity baseEntity = tr.GetObject(entities[0], OpenMode.ForWrite) as Entity; foreach (ObjectId id in entities) { EraseSingleObjectFromDrawingWithId(id); } DrawBlockFacingAPoint(record.Name, record.Origin, record.Origin, baseEntity.Layer, null); tr.Commit(); } } } public static void EraseSingleObjectFromDrawingWithId(ObjectId idOfObjectToErase) { // Start a transaction using (Transaction tr = _database.TransactionManager.StartTransaction()) { DBObject objToErase = tr.GetObject(idOfObjectToErase, OpenMode.ForWrite); // Check to make sure a valid SelectedObject object was returned if (objToErase != null) { objToErase.Erase(); } tr.Commit(); } } public static BlockReference DrawBlockFacingAPoint(string name, Point3d position, Point3d direction, string layerToInsertOn, List<string> attributeValues = null, Distance xScale = null, Distance yScale = null, Distance zScale = null) { LastPositionPoint = position; LastDirectionPoint = direction; //Creating default distances if null is passed for the scales if (xScale == null) { xScale = new Distance(DistanceType.Inch, 1); } if (yScale == null) { yScale = new Distance(DistanceType.Inch, 1); } if (zScale == null) { zScale = new Distance(DistanceType.Inch, 1); } ObjectId blkRecId = _generateBlockRecordId(name); //Generating ID for the block BlockReference blkRef = null; //Reference of the block that will be inserted using (Transaction tr = _database.TransactionManager.StartTransaction()) //Starting the transaction to insert the block into the drawing using (DocumentLock docLock = _activeDocument.LockDocument()) { blkRef = new BlockReference(position, blkRecId); //Creating the block reference blkRef.SetDatabaseDefaults(); blkRef.ScaleFactors = new Scale3d(xScale.Inches, yScale.Inches, zScale.Inches); //Changing the scales to what the programmer specifies blkRef.Layer = layerToInsertOn; //Assigning layer to draw the block on Point start = Point.MakePointWithInches(position.X, position.Y, position.Z); //Generating first AutoCAD point Point end = Point.MakePointWithInches(direction.X, direction.Y, direction.Z); //Generating second AutoCAD point GeometryClassLibrary.Line line = new GeometryClassLibrary.Line(start, end); //Creating a line to mirror a block over if necessary Angle a = new Angle(AngleType.Radian, 0); //Angle to rotate the block by //Assigning angle based on direction point if (position.Y != direction.Y) { a = line.AngleBetween(GeometryClassLibrary.Line.XAxis); } if (direction.Y < position.Y) { blkRef.Rotation = a.Negate().GetValue(AngleType.Radian); //Allowing for rotations beyond 180 degrees } else { blkRef.Rotation = a.GetValue(AngleType.Radian); } BlockTableRecord blkTblRec = tr.GetObject(_database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord; blkTblRec.AppendEntity(blkRef); //Adding block referece to the block table of the drawing tr.AddNewlyCreatedDBObject(blkRef, true); //Adding block to the drawing //Assigning attributes of the block BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead); int attCounter = 0; //Counter to iterate through attributes foreach (ObjectId objId in btr) //Checking each item in the BlockReference's records { DBObject obj = objId.GetObject(OpenMode.ForRead); if (obj is AttributeDefinition) //If the object is an attribute, update it. { AttributeDefinition ad = obj as AttributeDefinition; AttributeReference ar = new AttributeReference(); ar.SetAttributeFromBlock(ad, blkRef.BlockTransform); ar.Position = ad.Position.TransformBy(blkRef.BlockTransform); try { ar.TextString = attributeValues.ElementAt(attCounter); } catch (ArgumentNullException) { ar.TextString = ""; } catch (ArgumentOutOfRangeException) { ar.TextString = ""; } attCounter++; blkRef.AttributeCollection.AppendAttribute(ar); tr.AddNewlyCreatedDBObject(ar, true); } } tr.Commit(); return blkRef; } } private static ObjectId _generateBlockRecordId(string passedBlockName) { Transaction tr = _database.TransactionManager.StartTransaction(); DocumentLock docLock = _activeDocument.LockDocument(); using (tr) using (docLock) { BlockTable blkTbl = tr.GetObject(_database.BlockTableId, OpenMode.ForRead) as BlockTable; ObjectId blkRecId = ObjectId.Null; if (blkTbl.Has(passedBlockName)) //Checking if the block exists { blkRecId = blkTbl[passedBlockName]; //If it does, getting the current id } else //If it doesn't exist create one { Database blkDb = new Database(false, true); blkDb.ReadDwgFile(passedBlockName + ".dwg", System.IO.FileShare.Read, true, ""); //Reading block source file _database.Insert(passedBlockName, blkDb, true); blkRecId = blkTbl[passedBlockName]; } return blkRecId; } } Sorry there's so many methods involved. I think the problem lies in actually drawing the block but I included all the involved methods just in case. Anyways, the methods succeed in creating a block definition and drawing an instance of that block in place of the group of lines. Problem is the block is still a wireframe. If anyone knows how to change this approach to draw solid blocks I will be wicked grateful!
Source: https://stackoverflow.com/questions/31896917/creating-a-solid-block-from-a-group-of-lines-in-autocad-c
0 Response to "Autocad C Custom Draw Ling"
Post a Comment