TheSwamp

Code Red => .NET => Topic started by: Roland Feletic on January 30, 2007, 07:09:54 AM

Title: Copy SelectionSet with dynamic blocks
Post by: Roland Feletic on January 30, 2007, 07:09:54 AM
With the help of some of you i've made a code which copies a selectionset along a curve.
When i have dynamic blocks in this selection set just the anonymous block will be copied and the block looses all it's dynamic properties.
What must i do to copy dynmic blocks correctly?

Code: [Select]
#region Using directives
using System;
using System.Collections;
using System.Collections.Generic;

using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;

using RSNNAcadApp.ExtendedCommands;
#endregion

[assembly: CommandClass(typeof(RSNNAcadApp.ExtendedCommands.Copy))]
namespace RSNNAcadApp.ExtendedCommands
{
    class Copy
    {
        private Matrix3d UcsMatrix;
        private Point3d m_basePoint;
        private Point3d m_destinationPoint;
        private Curve BaseCurve;
        private Matrix3d transMat;

        private Vector3d xAxisFrom, yAxisFrom, zAxisFrom;
        private Vector3d xAxisTo, yAxisTo, zAxisTo;
       
        /// <summary>
        /// Copies blockreferences along a Curve with a given distance
        /// </summary>
        [CommandMethod("KOPIERENENTLANGMITBASIS", CommandFlags.UsePickSet)]
        public void CopyAlongCurve()
        {
            Database db = HostApplicationServices.WorkingDatabase;
            //Transaction myT = db.TransactionManager.StartTransaction();
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

            try
            {

                PromptSelectionOptions ssOptions = new PromptSelectionOptions();
                ssOptions.MessageForAdding = "\nObjekte wählen: ";
                ssOptions.MessageForRemoval = "\nObjekte entfernen: ";
                ssOptions.AllowDuplicates = true;


                PromptSelectionResult ssResult = ed.GetSelection(ssOptions);
                if (ssResult.Status != PromptStatus.OK)
                    return;
                if (ssResult.Value.Count == 0)
                    return;

                PromptEntityOptions entOptions = new PromptEntityOptions("\nBezugslinie wählen, entlang der kopiert werden soll");
                entOptions.SetRejectMessage("\nNur Kurven können gewählt werden.");
                entOptions.AddAllowedClass(typeof(Curve), false);
                PromptEntityResult entResult = ed.GetEntity(entOptions);
                if (entResult.Status != PromptStatus.OK)
                    return;
                ObjectId BaseCurveId = entResult.ObjectId;
                //Get a base point from the user
                PromptPointResult pointResult = ed.GetPoint("\nBasispunkt: ");
                if (pointResult.Status != PromptStatus.OK)
                    return;
                UcsMatrix = ed.CurrentUserCoordinateSystem;
                m_basePoint = pointResult.Value.TransformBy(UcsMatrix);

                do
                {
                    using (Transaction myT = db.TransactionManager.StartTransaction())
                    {
                        BaseCurve = (Curve)myT.GetObject(BaseCurveId, OpenMode.ForRead);
                        if (BaseCurve == null)
                            return;

                        Point3d tmpbasePoint = BaseCurve.GetClosestPointTo(m_basePoint, false);

                        xAxisFrom = BaseCurve.GetFirstDerivative(tmpbasePoint).GetNormal();
                        yAxisFrom = BaseCurve.GetSecondDerivative(tmpbasePoint).GetNormal();
                        if (yAxisFrom.IsZeroLength() || !yAxisFrom.IsPerpendicularTo(xAxisFrom))
                        {
                            if (BaseCurve.IsPlanar)
                                yAxisFrom = BaseCurve.GetPlane().Normal.CrossProduct(xAxisFrom.GetNormal()).GetNormal();
                            else
                                yAxisFrom = xAxisFrom.GetPerpendicularVector().GetNormal();
                        }
                        zAxisFrom = xAxisFrom.CrossProduct(yAxisFrom).GetNormal();

                        //Initiate the drag callback delegate
                        DragCallback dragCallbackDelegate = this.FollowCursor;

                        //Start the drag operation
                        PromptDragOptions dragOptions = new PromptDragOptions(ssResult.Value, "\nZweiter Punkt angeben oder", dragCallbackDelegate);
                        string kwDefault = "Beenden";
                        dragOptions.Keywords.Add(kwDefault);
                        dragOptions.Keywords.Default = kwDefault;
                        PromptPointResult destinationPointResult = ed.Drag(dragOptions);
                        if (destinationPointResult.Status != PromptStatus.OK)
                            return;

                        m_destinationPoint = destinationPointResult.Value.TransformBy(UcsMatrix);
                        //m_destinationPoint = destinationPointResult.Value;
                        Point3d tmpdestinationPoint = BaseCurve.GetClosestPointTo(m_destinationPoint, false);

                        xAxisTo = BaseCurve.GetFirstDerivative(tmpdestinationPoint).GetNormal();
                        yAxisTo = BaseCurve.GetSecondDerivative(tmpdestinationPoint).GetNormal();
                        if (yAxisTo.IsZeroLength() || !yAxisTo.IsPerpendicularTo(xAxisTo))
                        {
                            if (BaseCurve.IsPlanar)
                                yAxisTo = BaseCurve.GetPlane().Normal.CrossProduct(xAxisTo.GetNormal()).GetNormal();
                            else
                                yAxisTo = xAxisTo.GetPerpendicularVector().GetNormal();
                        }
                        zAxisTo = xAxisTo.CrossProduct(yAxisTo).GetNormal();

                        //Determine the final displacement matrix
                        transMat = Matrix3d.AlignCoordinateSystem(
                            m_basePoint, xAxisFrom, yAxisFrom, zAxisFrom,
                            m_destinationPoint, xAxisTo, yAxisTo, zAxisTo);

                        myT.Commit();
                    }

                    //transform the ss to the new location
                    this.TransformSelectionSet(ssResult.Value, transMat);
                } while (true);
           
            }
            finally
            {
                //myT.Dispose();
            }

        }

        //DragCallback Delegate
        public SamplerStatus FollowCursor(Point3d currentPoint, ref Matrix3d transMat)
        {
            Point3d tmpcurrentPoint = BaseCurve.GetClosestPointTo(currentPoint.TransformBy(UcsMatrix), false);
            xAxisTo = BaseCurve.GetFirstDerivative(tmpcurrentPoint).GetNormal();
            yAxisTo = BaseCurve.GetSecondDerivative(tmpcurrentPoint).GetNormal();
            if (yAxisTo.IsZeroLength() || !yAxisTo.IsPerpendicularTo(xAxisTo))
            {
                if (BaseCurve.IsPlanar)
                    yAxisTo = BaseCurve.GetPlane().Normal.CrossProduct(xAxisTo.GetNormal()).GetNormal();
                else
                    yAxisTo = xAxisTo.GetPerpendicularVector().GetNormal();
            }
            zAxisTo = xAxisTo.CrossProduct(yAxisTo).GetNormal();

            //Determine the final displacement matrix
            transMat = Matrix3d.AlignCoordinateSystem(
                m_basePoint, xAxisFrom, yAxisFrom, zAxisFrom,
                currentPoint.TransformBy(UcsMatrix), xAxisTo, yAxisTo, zAxisTo);

            return SamplerStatus.OK;
        }


        private void TransformSelectionSet(SelectionSet ss, Matrix3d transMat)
        {
            if (ss.Count == 0)
            {
                return;
            }

            Database targetDatabase = ss[0].ObjectId.Database;

            using (Transaction trans = targetDatabase.TransactionManager.StartTransaction())
            {
                BlockTableRecord currentSpace = (BlockTableRecord)trans.GetObject(targetDatabase.CurrentSpaceId, OpenMode.ForWrite);

                foreach (SelectedObject selectedObj in ss)
                {
                    Entity selectedEntity = (Entity)trans.GetObject(selectedObj.ObjectId, OpenMode.ForRead);

                    Entity transformedEntity = selectedEntity.GetTransformedCopy(transMat);

                    currentSpace.AppendEntity(transformedEntity);

                    trans.AddNewlyCreatedDBObject(transformedEntity, true);
                }

                trans.Commit();
            }
        }


    }
}