Result IExternalCommand.Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
// cache admin data
_appUI = commandData.Application;
_app = _appUI.Application;
_docUI = commandData.Application.ActiveUIDocument;
_doc = _docUI.Document;
try // generic
{
// Current View must be Sheet
ViewSheet sheet = _doc.ActiveView as ViewSheet;
if( null == sheet )
{
Util.ErrorMsg( "Current View is NOT a Sheet!" );
return Result.Cancelled;
}
// There must be a Floor Plan named "Level 0"
// which is the "master" to align to
Viewport vpMaster = null;
// There must be at least one more Floor Plan
// View to align (move)
List<Viewport> vpsSlave = new List<Viewport>();
// Find them:
foreach( ElementId idVp in sheet.GetAllViewports() )
{
Viewport vp = _doc.GetElement( idVp ) as Viewport;
ViewRvt v = _doc.GetElement( vp.ViewId ) as ViewRvt;
if( v.ViewType == ViewType.FloorPlan )
{
if( v.Name.Equals( "Level 0", StringComparison
.CurrentCultureIgnoreCase ) )
{
vpMaster = vp;
}
else
{
vpsSlave.Add( vp );
}
} //if FloorPlan
} //foreeach idVp
// Check if got them all
if( null == vpMaster )
{
Util.ErrorMsg( "NO 'Level 0' Floor Plan on the Sheet!" );
return Result.Cancelled;
}
else if( vpsSlave.Count == 0 )
{
Util.ErrorMsg( "NO other Floor Plans to adjust on the Sheet!" );
return Result.Cancelled;
}
// Process Master
// --------------
XYZ ptMasterVpCenter = vpMaster.GetBoxCenter();
ViewRvt viewMaster = _doc.GetElement(
vpMaster.ViewId ) as ViewRvt;
double scaleMaster = viewMaster.Scale;
// Process Slaves
// --------------
using ( Transaction t = new Transaction( _doc ) )
{
t.Start( "Set Box Centres" );
foreach ( Viewport vpSlave in vpsSlave )
{
XYZ ptSlaveVpCenter = vpSlave.GetBoxCenter();
ViewRvt viewSlave = _doc.GetElement(
vpSlave.ViewId ) as ViewRvt;
double scaleSlave = viewSlave.Scale;
// MUST be the same scale, otherwise can't really overlap
if ( scaleSlave != scaleMaster ) continue;
// Work out how to move the center of Slave
// Viewport to coincide model-wise with Master
// (must use center as only Viewport.SetBoxCenter
// is provided in API)
// We can ignore View.Outline as Viewport.GetBoxOutline
// is ALWAYS the same dimensions enlarged by
// 0.01 ft in each direction.
// This guarantees that the center of View is
// also center of Viewport, BUT there is a
// problem when any Elevation Symbols outside
// the crop box are visible (can't work out why
// - BUG?, or how to calculate it all if BY-DESIGN)
BoundingBoxXYZ bbm = viewMaster.CropBox;
BoundingBoxXYZ bbs = viewSlave.CropBox;
// 0) Center points in WCS
XYZ wcsCenterMaster = 0.5 * bbm.Min.Add( bbm.Max );
XYZ wcsCenterSlave = 0.5 * bbs.Min.Add( bbs.Max );
// 1) Delta (in model's feet) of the slave center w.r.t master center
double deltaX = wcsCenterSlave.X - wcsCenterMaster.X;
double deltaY = wcsCenterSlave.Y - wcsCenterMaster.Y;
// 1a) Scale to Delta in Sheet's paper-space feet
deltaX *= 1.0 / (double) scaleMaster;
deltaY *= 1.0 / (double) scaleMaster;
// 2) New center point for the slave viewport, so *models* "overlap":
XYZ newCenter = new XYZ(
ptMasterVpCenter.X + deltaX,
ptMasterVpCenter.Y + deltaY,
ptSlaveVpCenter.Z );
vpSlave.SetBoxCenter( newCenter );
}
t.Commit();
}
}
catch( Exception ex )
{
Util.ErrorMsg( "Generic exception: " + ex.Message );
return Result.Failed;
}
return Result.Succeeded;
}