Deep clone associative hatch to polyline

Deep clone associative hatch to polyline

mahmoudali9316
Explorer Explorer
894 Views
4 Replies
Message 1 of 5

Deep clone associative hatch to polyline

mahmoudali9316
Explorer
Explorer

Hi all,

I'm trying to override ObjectOverrule.DeepClone behavior to copy ployline and it's associative hatches.Associative HatchAssociative Hatch

the following code throws exception when trying to copy hatches.

public override DBObject DeepClone(DBObject dbObject, DBObject ownerObject, IdMapping idMap, bool isPrimary)
{
     Document document = Application.DocumentManager.GetDocument(dbObject.Database);
     DBObject clonedObject = base.DeepClone(dbObject, ownerObject, idMap, isPrimary);
      //Copy Hatch
     ObjectIdCollection persistentID = dbObject.GetPersistentReactorIds();
     IdMapping map = new IdMapping();
     document.Database.DeepCloneObjects(persistentID, document.Database.CurrentSpaceId, map, false);   
     return clonedObject;
}  


ExceptionExceptionThanks in advance.

 

0 Likes
Accepted solutions (1)
895 Views
4 Replies
Replies (4)
Message 2 of 5

tbrammer
Advisor
Advisor

You are calling

 

ObjectIdCollection persistentID = dbObject.GetPersistentReactorIds();
document.Database.DeepCloneObjects(persistentID, document.Database.CurrentSpaceId, ..);   

without checking

  • the number of persistent reactors in persistentID
  • the owners and classes of the reactors in persistentID

I suppose the exception is caused, because you are cloning objects to document.Database.CurrentSpaceId, (which is either the model space or paper space), that are no entities. Or maybe because persistentID is empty.

 

I checked the hatch of a hatched polyline with the ArxDbg.arx (from <ARX>\samples\database\ARXDBG) and it had no persistent reactors at all. Only the polyline had the hatch as persistent reactor.

 


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes
Message 3 of 5

mahmoudali9316
Explorer
Explorer

I have written command method to check Ids of hatches before copying polyline as in the following image.PrintIdPolyline.png

 

and then I called copy command to copy polyline and checked number of PersistentReactorIds as in the following image.persistenceId.png

notice that :

-persistentID.Count=2.

-it has same ids.

0 Likes
Message 4 of 5

mahmoudali9316
Explorer
Explorer

I Solved the problem by opening a transaction then looping through persistentIDs to clone hatches and then remove hatch loop and assign new cloned Polyline to it. (as in following code)

      public override DBObject DeepClone(DBObject dbObject, DBObject ownerObject, IdMapping idMap, bool isPrimary)
        {
            var document = Application.DocumentManager.GetDocument(dbObject.Database);
            DBObject clonedObject = base.DeepClone(dbObject, ownerObject, idMap, isPrimary);
            //Copy Hatch
            ObjectIdCollection persistentIDs = clonedObject.GetPersistentReactorIds();
            if (persistentIDs.Count > 0)
            {
                using (Transaction trans = document.Database.TransactionManager.StartTransaction())
                {
                    BlockTableRecord currentSpace = trans.GetObject(document.Database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                    Polyline clonedPoly = trans.GetObject(clonedObject.Id, OpenMode.ForWrite) as Polyline;
                    ObjectIdCollection clonedPolyIds = new ObjectIdCollection { clonedPoly.ObjectId };
                    foreach (ObjectId ObjID in persistentIDs)
                    {
                        IdMapping map = new IdMapping();
                        document.Database.DeepCloneObjects(new ObjectIdCollection { ObjID }, currentSpace.Id, map, false);
                        foreach (IdPair idPair in map)
                        {
                            Hatch clonedHatch = trans.GetObject(idPair.Value, OpenMode.ForWrite) as Hatch;
                            if (clonedHatch != null)
                            {
                                clonedHatch.Associative = false;
                                clonedHatch.RemoveAssociatedObjectIds();
                                for (int i = 0; i < clonedHatch.NumberOfLoops; ++i)
                                    clonedHatch.RemoveLoopAt(i);

                                clonedHatch.Associative = true;
                                clonedHatch.AppendLoop(HatchLoopTypes.External, clonedPolyIds);
                            }
                        }
                    }
                    trans.Commit();
                }
            }
            return clonedObject;
        }

however, there is another problem.

After copying polyline I need to call Regen command to show hatch within polyline (1 hatch).Untitled.png

 

to show transparent hatch, i need to move polyline.Untitled.png

 

 How can I solve this problem using API?

0 Likes
Message 5 of 5

mahmoudali9316
Explorer
Explorer
Accepted solution

I solved the problem by using IdMapping of Deep Clone function instead of defining new instance.

 public override DBObject DeepClone(DBObject dbObject, DBObject ownerObject, IdMapping idMap, bool isPrimary)
        {
            var document = Application.DocumentManager.GetDocument(dbObject.Database);
            DBObject clonedObject = base.DeepClone(dbObject, ownerObject, idMap, isPrimary);
            //Copy Hatch
            ObjectIdCollection persistentIDs = clonedObject.GetPersistentReactorIds();
            if (persistentIDs.Count > 0)
            {
                using (Transaction trans = document.Database.TransactionManager.StartTransaction())
                {
                    BlockTableRecord currentSpace = trans.GetObject(document.Database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                    Polyline clonedPoly = trans.GetObject(clonedObject.Id, OpenMode.ForWrite) as Polyline;
                    ObjectIdCollection clonedPolyIds = new ObjectIdCollection { clonedPoly.ObjectId };
                    foreach (ObjectId ObjID in persistentIDs)
                    {
//Never create a new instance of AcDbIdMapping to pass to the cloning function of the dependent reference. //IdMapping map = new IdMapping(); document.Database.DeepCloneObjects(new ObjectIdCollection { ObjID }, currentSpace.Id, idMap, false); foreach (IdPair idPair in idMap) { Hatch clonedHatch = trans.GetObject(idPair.Value, OpenMode.ForWrite) as Hatch; if (clonedHatch != null) { clonedHatch.Associative = false; clonedHatch.RemoveAssociatedObjectIds(); for (int i = 0; i < clonedHatch.NumberOfLoops; ++i) clonedHatch.RemoveLoopAt(i); clonedHatch.Associative = true; clonedHatch.AppendLoop(HatchLoopTypes.External, clonedPolyIds); } } } trans.Commit(); } } return clonedObject; }

See ObjectARX: Developer's Guide -> Advanced topic ->Deep cloning->Implementing deepClone() for custom classes.

there is note says that : Never create a new instance of AcDbIdMapping to pass to the cloning function of the dependent reference.

 

0 Likes