问题
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