Revit Transform Matrix from point cloud to revit link

浪子不回头ぞ 提交于 2019-12-11 16:03:40

问题


We insert a point cloud in Revit and have to move and rotate it in several axles to get a good world alignment. We then need to apply the same transforms to a Revit MEP link that contains edgwise piping. I have acquired the 3x4 matrix from the point cloud in revit, I would like to apply that to the revit mep link so that they are in alignment.

I have successfully applied the translation portion of the transform, I am stuck on the rotation portion. Could someone please assist with this. Dyslexia and Matrices do not work well together.

Thanks to Jeremy at the Building Coder for getting me this far!

9/4/19 - I edited the rotational part of the code, however the "ElementTransformUtils.RotateElement" does not have any effect on the link in Revit.

Autodesk.Revit.DB.View
pView = ActiveUIDocument.Document.ActiveView;Autodesk.Revit.DB.Transaction
    t = new Autodesk.Revit.DB.Transaction(ActiveUIDocument.Document, "EdgewiseCoordination");
    t.Start();

        UIDocument uidoc = this.ActiveUIDocument;
        Document document = uidoc.Document;
        Autodesk.Revit.ApplicationServices.Application application = document.Application;

        ElementId elementid = null;
        elementid = uidoc.Selection.PickObject(ObjectType.Element, "Select element to Copy Transform or ESC to reset the view").ElementId;

            Element e = document.GetElement(elementid);

            Instance ei = e as Instance;

            Transform pct = ei.GetTransform();

        ElementId elementid2 = null;
            elementid2 = uidoc.Selection.PickObject(ObjectType.Element, "Select element to Apply Transform or ESC to reset the view").ElementId;

                Element e2 = document.GetElement(elementid2);

                Instance ei2 = e2 as Instance;

                ElementTransformUtils.MoveElement(document,elementid2,pct.Origin);

                Line lineaxis = GetRotationAxisFromTransform(pct);
                double tangle = GetRotationAngleFromTransform(pct);

                ElementTransformUtils.RotateElement(document,elementid2,lineaxis,tangle);

        t.Commit(); 

}


private static Line GetRotationAxisFromTransform(Transform transform)
{
  double x = transform.BasisY.Z - transform.BasisZ.Y;
  double y = transform.BasisZ.X - transform.BasisX.Z;
  double z = transform.BasisX.Y - transform.BasisY.X;

  return Line.CreateUnbound(transform.Origin, new XYZ(x, y, z));
}

private static double GetRotationAngleFromTransform(Transform transform)
{
  double x = transform.BasisX.X;
  double y = transform.BasisY.Y;
  double z = transform.BasisZ.Z;

  double trace = x + y + z;

  return Math.Acos((trace - 1) / 2.0);
}       



Earlier Code to save out the transform----------------------------------

public void Objectlocation()
{

    Autodesk.Revit.DB.View
    pView = ActiveUIDocument.Document.ActiveView;Autodesk.Revit.DB.Transaction
        t = new Autodesk.Revit.DB.Transaction(ActiveUIDocument.Document, "Objectlocation");
        t.Start();

            UIDocument uidoc = this.ActiveUIDocument;
            Document document = uidoc.Document;
            Autodesk.Revit.ApplicationServices.Application application = document.Application;

            ElementId elementid = null;
            elementid = uidoc.Selection.PickObject(ObjectType.Element, "Select element or ESC to reset the view").ElementId;

                Element e = document.GetElement(elementid);

                Instance ei = e as Instance;

                Transform pct = ei.GetTransform();

                //string spctrans = TransformString(pct);
                //TaskDialog.Show("Point Cloud Transform", spctrans);

                //spctrans = (spctrans + ",0,0,0,1");

                string slocx = TransformStringX(pct);
                string slocy = TransformStringY(pct);
                string slocz = TransformStringZ(pct);

                string slocation = (slocx + "," + slocy + "," + slocz + ",0,0,0,1");

                using (StreamWriter sw = new StreamWriter("test.txt"))
                {
                   sw.WriteLine(slocation);
                }

        t.Commit(); 

}

static public string RealString( double a )
{
return a.ToString( "0.####################" );
}

static public string PointStringX( XYZ p )
{
    double convunit = 0;
    convunit = UnitUtils.ConvertFromInternalUnits(p.X,DisplayUnitType.DUT_DECIMAL_INCHES);

return string.Format( "{0}", RealString( convunit ));
}

static public string TransformStringX( Transform t )
{
return string.Format( "{0},{1},{2},{3}", PointStringX( t.BasisX ),
PointStringX( t.BasisY ), PointStringX( t.BasisZ ), PointStringX( t.Origin ) );
}

static public string PointStringY( XYZ p )
{
    double convunit = 0;
    convunit = UnitUtils.ConvertFromInternalUnits(p.Y,DisplayUnitType.DUT_DECIMAL_INCHES);
return string.Format( "{0}", RealString( convunit ));
}

static public string TransformStringY( Transform t )
{
return string.Format( "{0},{1},{2},{3}", PointStringY( t.BasisX ),
PointStringY( t.BasisY ), PointStringY( t.BasisZ ), PointStringY( t.Origin ) );
}

static public string PointStringZ( XYZ p )
{
    double convunit = 0;
    convunit = UnitUtils.ConvertFromInternalUnits(p.Z,DisplayUnitType.DUT_DECIMAL_INCHES);
return string.Format( "{0}", RealString( convunit ));
}

static public string TransformStringZ( Transform t )
{
return string.Format( "{0},{1},{2},{3}", PointStringZ( t.BasisX ),
PointStringZ( t.BasisY ), PointStringZ( t.BasisZ ), PointStringZ( t.Origin ) );
}


I edited the stuff you had on bcoder to split up the matrix in order to match the acad api that I was feeding it into.

ACAD API below-----------------------------------------------------------


using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.Runtime;

using System.Reflection;



namespace Transformer

{

    public class Commands

    {

        [CommandMethod("TRANS", CommandFlags.UsePickSet)]

        static public void TransformEntity()

        {

            Document doc =

              Application.DocumentManager.MdiActiveDocument;

            Database db = doc.Database;

            Editor ed = doc.Editor;



            // Our selected entity (only one supported, for now)



            ObjectId id;



            // First query the pickfirst selection set



            PromptSelectionResult psr = ed.SelectImplied();

            if (psr.Status != PromptStatus.OK || psr.Value == null)

            {

                // If nothing selected, ask the user



                PromptEntityOptions peo =

                  new PromptEntityOptions(

                    "\nSelect entity to transform: "

                  );

                PromptEntityResult per = ed.GetEntity(peo);

                if (per.Status != PromptStatus.OK)

                    return;

                id = per.ObjectId;

            }

            else

            {

                // If the pickfirst set has one entry, take it



                SelectionSet ss = psr.Value;

                if (ss.Count != 1)

                {

                    ed.WriteMessage(

                      "\nThis command works on a single entity."

                    );

                    return;

                }

                ObjectId[] ids = ss.GetObjectIds();

                id = ids[0];

            }



            PromptResult pr = ed.GetString("\nEnter property name: ");

            if (pr.Status != PromptStatus.OK)

                return;



            string prop = pr.StringResult;



            // Now let's ask for the matrix string



            pr = ed.GetString("\nEnter matrix values: ");

            if (pr.Status != PromptStatus.OK)

                return;



            // Split the string into its individual cells



            string[] cells = pr.StringResult.Split(new char[] { ',' });

            if (cells.Length != 16)

            {

                ed.WriteMessage("\nMust contain 16 entries.");

                return;

            }



            try

            {

                // Convert the array of strings into one of doubles



                double[] data = new double[cells.Length];

                for (int i = 0; i < cells.Length; i++)

                {

                    data[i] = double.Parse(cells[i]);

                }



                // Create a 3D matrix from our cell data



                Matrix3d mat = new Matrix3d(data);



                // Now we can transform the selected entity



                Transaction tr =

                  doc.TransactionManager.StartTransaction();

                using (tr)

                {

                    Entity ent =

                      tr.GetObject(id, OpenMode.ForWrite)

                      as Entity;

                    if (ent != null)

                    {

                        bool transformed = false;



                        // If the user specified a property to modify



                        if (!string.IsNullOrEmpty(prop))

                        {

                            // Query the property's value



                            object val =

                              ent.GetType().InvokeMember(

                                prop, BindingFlags.GetProperty, null, ent, null

                              );



                            // We only know how to transform points and vectors



                            if (val is Point3d)

                            {

                                // Cast and transform the point result



                                Point3d pt = (Point3d)val,

                                        res = pt.TransformBy(mat);



                                // Set it back on the selected object



                                ent.GetType().InvokeMember(

                                  prop, BindingFlags.SetProperty, null,

                                  ent, new object[] { res }

                                );

                                transformed = true;

                            }

                            else if (val is Vector3d)

                            {

                                // Cast and transform the vector result



                                Vector3d vec = (Vector3d)val,

                                        res = vec.TransformBy(mat);



                                // Set it back on the selected object



                                ent.GetType().InvokeMember(

                                  prop, BindingFlags.SetProperty, null,

                                  ent, new object[] { res }

                                );

                                transformed = true;

                            }

                        }



                        // If we didn't transform a property,

                        // do the whole object



                        if (!transformed)

                            ent.TransformBy(mat);

                    }

                    tr.Commit();

                }

            }

            catch (Autodesk.AutoCAD.Runtime.Exception ex)

            {

                ed.WriteMessage(

                  "\nCould not transform entity: {0}", ex.Message

                );

            }

        }

    }

}

END ACAD API


来源:https://stackoverflow.com/questions/57775794/revit-transform-matrix-from-point-cloud-to-revit-link

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!