Here's something that may prove useful.
This is a command in the soon-to-be-released SincpacC3D v1.0. It lets you select a bunch of objects, and then change them to match the rotation of another selected object. If the object to match is a linear object such as a polyline or an arc (or Civil-3D Feature Line or Parcel Line), then the routine uses the direction of the linear object at the point that is closest to the user's pick point.
This code uses other code that already exists in the SincpacC3D, so if you want to actually run it, you will need to add this code to the SincpacC3D source code, which can be downloaded from
here.
In the very near future, I plan to release a super-improved version of the SincpacC3D, with more than twice as many useful commands as the current version, as well as new-and-improved versions of existing routines, and also integrated Help for all functions. It provides quick'n'easy solutions to many of the problems people have been complaining about on Autodesk's discussion groups, so I've been trying to get it ready for release as quickly as possible. It's getting close to being ready, and I hope to have it available within the next few weeks. But here's a sneak-peak of one of the simpler (but still very useful) routines:
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AECC.Interop.Land;
using AutocadUtilities;
using Civil3DUtilities;
namespace SincpacC3D.RotateObjects
{
public class RotationMatch
{
[CommandMethod("ROTATIONMATCH", CommandFlags.UsePickSet)]
public void RotationMatchCommand()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
C3DUtil c3dUtil = new C3DUtil();
Database db = Application.DocumentManager.MdiActiveDocument.Database;
PromptSelectionOptions sPrmpt = new PromptSelectionOptions();
sPrmpt.MessageForAdding = "\nSelect objects to rotate: ";
sPrmpt.MessageForRemoval = "\nSelect objects to remove: ";
PromptSelectionResult ssResult;
ssResult = ed.GetSelection(sPrmpt);
if (ssResult.Status == PromptStatus.OK)
{
PromptEntityOptions entityOps = new PromptEntityOptions("\nSelect object to match: ");
PromptEntityResult entityRes = ed.GetEntity(entityOps);
if (entityRes.Status == PromptStatus.OK)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
ObjectId[] objIds = ssResult.Value.GetObjectIds();
Entity matchEntity = tr.GetObject(entityRes.ObjectId, OpenMode.ForRead, false) as Entity;
double rot = 0;
int errorCount = 0;
Curve crv = matchEntity as Curve;
if (crv != null)
{
Point3d pickPt = entityRes.PickedPoint;
Point3d pointOnCurve = crv.GetClosestPointTo(pickPt, false);
rot = CurveUtil.AzimuthAtParam(crv, crv.GetParameterAtPoint(pointOnCurve));
}
else
{
try
{
rot = (double)matchEntity.GetType().GetProperty("Rotation").GetValue(matchEntity, null);
}
catch
{
AeccPoint p = matchEntity.AcadObject as AeccPoint;
if (p != null)
{
rot = p.Rotation;
}
else
{
ed.WriteMessage("\nCould not get rotation for selected object...");
}
}
}
foreach (ObjectId oId in objIds)
{
Entity ent = tr.GetObject(oId, OpenMode.ForWrite, false) as Entity;
try
{
ent.GetType().GetProperty("Rotation").SetValue(ent, rot, null);
}
catch
{
Line line = ent as Line;
if (line != null)
{
LineSegment2d calcLine = new LineSegment2d(line.StartPoint.Convert2d(CurveUtil.PlaneXY), line.EndPoint.Convert2d(CurveUtil.PlaneXY));
double dist = line.Length / 2;
double dX = Math.Cos(rot) * dist;
double dY = Math.Sin(rot) * dist;
Point2d midpoint = calcLine.MidPoint;
Point3d newStart = new Point3d(midpoint.X - dX, midpoint.Y - dY, line.StartPoint.Z);
Point3d newEnd = new Point3d(midpoint.X + dX, midpoint.Y + dY, line.EndPoint.Z);
line.StartPoint = newStart;
line.EndPoint = newEnd;
}
else
{
AeccPoint p = ent.AcadObject as AeccPoint;
if (p != null) p.Rotation = rot;
else ++errorCount;
}
}
}
if (errorCount > 0)
ed.WriteMessage("\nCould not rotate {0} object(s).", errorCount);
tr.Commit();
}
}
}
}
}
}