TheSwamp
Code Red => .NET => Topic started by: Jeff H on August 22, 2010, 01:23:14 AM
-
I am able to get the objects to show up in the xref drawing but they do not persist to the actual file. So if I detach the xref and attach it or open the actual file the objects are not there. To add the objects to the xref I was adding the transformed objects to the BlockTableRecord of the xref.
The code was getting pretty ugly from testing different ways so I cleaned it back up to sending the objects just to modelspace.
Here is the code and any ideas on how to get objects to persist to the xref would be greatly appreciated
Here is a command you select a viewport then the objects and its sends them to modelspace and erasing them from paperspace
I thought about checking the TILEMODE variable if modelspace was not active then if only one viewport was in the current space automatically selecting it, but there is always a viewport 2 if I add one
<CommandMethod("SendToModelSpace")> _
Public Shared Sub SendToModelSpace()
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor
Dim objIdsErase As New List(Of ObjectId)
Dim peo As New PromptEntityOptions(vbLf & "Select viewport")
peo.SetRejectMessage(vbLf & "Not a viewport ")
peo.AddAllowedClass(GetType(Viewport), True)
Dim per As PromptEntityResult = ed.GetEntity(peo)
If per.Status <> PromptStatus.OK Then
Exit Sub
End If
Using tr As Transaction = db.TransactionManager.StartTransaction()
Dim vp As Viewport = tr.GetObject(per.ObjectId, OpenMode.ForRead)
Dim PsToMsTransForm As Matrix3d = PaperToModel(vp)
Dim bt As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead)
Dim btrMs As BlockTableRecord = tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForRead)
Dim pso As PromptSelectionOptions = New PromptSelectionOptions
Dim psr As PromptSelectionResult = ed.GetSelection
If per.Status <> PromptStatus.OK Then
Return
Else
btrMs.UpgradeOpen()
End If
For Each id As ObjectId In psr.Value.GetObjectIds
Dim psEnt As Entity = tr.GetObject(id, OpenMode.ForRead)
objIdsErase.Add(psEnt.ObjectId)
Dim msEnt As Entity = psEnt.Clone()
msEnt.TransformBy(PsToMsTransForm)
btrMs.AppendEntity(msEnt)
tr.AddNewlyCreatedDBObject(msEnt, True)
Next
tr.Commit()
End Using
Using tr As Transaction = db.TransactionManager.StartTransaction()
Dim bt As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead)
Dim btrPs As BlockTableRecord = tr.GetObject(bt(BlockTableRecord.PaperSpace), OpenMode.ForWrite)
For Each objId As ObjectId In btrPs
If objIdsErase.Contains(objId) Then
Dim ent As Entity = objId.GetObject(OpenMode.ForWrite)
ent.Erase()
End If
Next
tr.Commit()
End Using
objIdsErase.Clear()
End Sub
Here’s the functions PaperToModel and ModelToPaper
PaperToModel is just the inverse of ModelToPaper so you could use it either way
Private Shared Function PaperToModel(ByVal vp As Viewport) As Matrix3d
Dim mx As Matrix3d = ModelToPaper(vp)
Return mx.Inverse()
End Function
Private Shared Function ModelToPaper(ByVal vp As Viewport) As Matrix3d
Dim vd As Vector3d = vp.ViewDirection
Dim vc As New Point3d(vp.ViewCenter.X, vp.ViewCenter.Y, 0)
Dim vt As Point3d = vp.ViewTarget
Dim cp As Point3d = vp.CenterPoint
Dim ta As Double = -vp.TwistAngle
Dim vh As Double = vp.ViewHeight
Dim hgt As Double = vp.Height
Dim wdh As Double = vp.Width
Dim scl As Double = vh / hgt
Dim lenLgh As Double = vp.LensLength
Dim zAx As Vector3d = vd.GetNormal()
Dim xAx As Vector3d = Vector3d.ZAxis.CrossProduct(vd)
Dim yAx As Vector3d
If Not xAx.IsZeroLength() Then
xAx = xAx.GetNormal()
yAx = zAx.CrossProduct(xAx)
ElseIf zAx.Z < 0 Then
xAx = Vector3d.XAxis * -1
yAx = Vector3d.YAxis
zAx = Vector3d.ZAxis * -1
Else
xAx = Vector3d.XAxis
yAx = Vector3d.YAxis
zAx = Vector3d.ZAxis
End If
Dim pscToDcs As Matrix3d = Matrix3d.Displacement(Point3d.Origin - cp)
pscToDcs = pscToDcs * Matrix3d.Scaling(scl, cp)
Dim dcsToWcs As Matrix3d = Matrix3d.Displacement(vc - Point3d.Origin)
Dim matCoords As Matrix3d = Matrix3d.AlignCoordinateSystem(Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis, Point3d.Origin, xAx, _
yAx, zAx)
dcsToWcs = matCoords * dcsToWcs
dcsToWcs = Matrix3d.Displacement(vt - Point3d.Origin) * dcsToWcs
dcsToWcs = Matrix3d.Rotation(ta, zAx, vt) * dcsToWcs
Dim perspMx As Matrix3d = Matrix3d.Identity
If vp.PerspectiveOn Then
Dim vs As Double = vh
Dim aspectRatio As Double = wdh / hgt
Dim adjustFactor As Double = 1.0 / 42.0
Dim adjustedLensLength As Double = vs * lenLgh * Math.Sqrt(1.0 + aspectRatio * aspectRatio) * adjustFactor
Dim eyeDistance As Double = vd.Length
Dim lensDistance As Double = eyeDistance - adjustedLensLength
Dim ed As Double = eyeDistance
Dim aLenLgth As Double = adjustedLensLength
Dim ld As Double = lensDistance
Dim data As Double() = New Double() {1, 0, 0, 0, 0, 1, _
0, 0, 0, 0, (aLenLgth - ld) / aLenLgth, ld * (ed - aLenLgth) / aLenLgth, _
0, 0, -1.0 / aLenLgth, ed / aLenLgth}
perspMx = New Matrix3d(data)
End If
Dim resultMx As Matrix3d = pscToDcs.Inverse() * perspMx * dcsToWcs.Inverse()
Return resultMx
End Function
-
I am working on my C# so here it is.
Please give me any suggetions. The reason I am starting C# is I feel for some reasons C# seems eaiser to see how the classes relate and to look at it and be able to visualize the way the code works. I did this Line by Line from the Vb so the layout might be different to what your use to.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using System.IO;
namespace HpadCadExamplesCS
{
public class HpadExamplesCS
{
[CommandMethod("SendToModelSpace")]
public static void SendToModelSpace()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
List<ObjectId> objectsIdsErase= new List<ObjectId>();
PromptEntityOptions peo = new PromptEntityOptions("\nSelect Viewport");
peo.SetRejectMessage("\nNot a Viewport");
peo.AddAllowedClass(typeof (Viewport),true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Viewport vp = (Viewport)tr.GetObject(per.ObjectId, OpenMode.ForRead);
Matrix3d PsToMsTransForm = PaperToModel(vp);
BlockTable bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
BlockTableRecord btrMs = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
PromptSelectionOptions pso = new PromptSelectionOptions();
PromptSelectionResult psr = ed.GetSelection();
if (psr.Status != PromptStatus.OK)
{
return;
}
else
{
btrMs.UpgradeOpen();
}
foreach (ObjectId id in psr.Value.GetObjectIds())
{
Entity psEnt = (Entity)tr.GetObject(id, OpenMode.ForRead);
objectsIdsErase.Add(psEnt.ObjectId);
Entity msEnt = (Entity)psEnt.Clone();
msEnt.TransformBy(PsToMsTransForm);
btrMs.AppendEntity(msEnt);
tr.AddNewlyCreatedDBObject(msEnt, true);
}
tr.Commit();
}
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
BlockTableRecord btrPaper = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.PaperSpace],(OpenMode.ForWrite));
foreach (ObjectId id in btrPaper)
{
if (objectsIdsErase.Contains(id))
{
Entity ent = (Entity)id.GetObject(OpenMode.ForWrite);
ent.Erase();
}
}
tr.Commit();
}
}
private static Matrix3d PaperToModel(Viewport vp)
{
Matrix3d mx = ModelToPaper(vp);
return mx.Inverse();
}
private static Matrix3d ModelToPaper(Viewport vp)
{
Vector3d vd = vp.ViewDirection;
Point3d vc = new Point3d(vp.ViewCenter.X, vp.ViewCenter.Y, 0);
Point3d vt = vp.ViewTarget;
Point3d cp = vp.CenterPoint;
double ta = -vp.TwistAngle;
double vh = vp.ViewHeight;
double height = vp.Height;
double width = vp.Width;
double scale = vh / height;
double lensLength = vp.LensLength;
Vector3d zaxis = vd.GetNormal();
Vector3d xaxis = Vector3d.ZAxis.CrossProduct(vd);
Vector3d yaxis;
if (!xaxis.IsZeroLength())
{
xaxis = xaxis.GetNormal();
yaxis = zaxis.CrossProduct(xaxis);
}
else if (zaxis.Z < 0)
{
xaxis = Vector3d.XAxis * -1;
yaxis = Vector3d.YAxis;
zaxis = Vector3d.ZAxis * -1;
}
else
{
xaxis = Vector3d.XAxis;
yaxis = Vector3d.YAxis;
zaxis = Vector3d.ZAxis;
}
Matrix3d pcsToDCS = Matrix3d.Displacement(Point3d.Origin - cp);
pcsToDCS = pcsToDCS * Matrix3d.Scaling(scale, cp);
Matrix3d dcsToWcs = Matrix3d.Displacement(vc - Point3d.Origin);
Matrix3d mxCoords = Matrix3d.AlignCoordinateSystem(Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis, Point3d.Origin,
xaxis, yaxis, zaxis);
dcsToWcs = mxCoords * dcsToWcs;
dcsToWcs = Matrix3d.Displacement(vt - Point3d.Origin) * dcsToWcs;
dcsToWcs = Matrix3d.Rotation(ta, zaxis, vt) * dcsToWcs;
Matrix3d perspectiveMx = Matrix3d.Identity;
if (vp.PerspectiveOn)
{
double vSize = vh;
double aspectRatio = width / height;
double adjustFactor = 1.0 / 42.0;
double adjstLenLgth = vSize * lensLength * Math.Sqrt(1.0 + aspectRatio * aspectRatio) * adjustFactor;
double iDist = vd.Length;
double lensDist = iDist - adjstLenLgth;
double[] dataAry = new double[] {1,0,0,0,0,1,0,0,0,0,
(adjstLenLgth-lensDist)/adjstLenLgth,lensDist*(iDist-adjstLenLgth)/adjstLenLgth,
0,0,-1.0/adjstLenLgth,iDist/adjstLenLgth};
perspectiveMx = new Matrix3d(dataAry);
}
Matrix3d finalMx = pcsToDCS.Inverse() * perspectiveMx * dcsToWcs.Inverse();
return finalMx;
}
}
}
-
Fro, it seems that either opening a new database or WblockCloneObjects is very sensitive as to many transactions are being used. The code below works fine but if you recomment the using you will find it doesnt.
Viewports-the first one is paperspace itself just to confuse everyone.
I presume you want to scale the entities by the vp scale, I didn't do that, but at 1to1 the below puts the objects in the right place
[CommandMethod("TESTING")]
public static void testany()
{
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
PromptSelectionResult psr = ed.GetSelection();
if (psr.Status != PromptStatus.OK) return;
ObjectIdCollection ids = new ObjectIdCollection(psr.Value.GetObjectIds());
//using (Transaction tr = db.TransactionManager.StartTransaction())
//{ if you use this transaction nothing works
AddPaperspaceToXref(ids, "1");
//}
}
public static void AddPaperspaceToXref(ObjectIdCollection ids,string sXref)
{
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord Xref = tr.GetObject(bt[sXref], OpenMode.ForRead) as BlockTableRecord;
string path = Xref.PathName;
Database dbase = new Database(false, false);
try
{
dbase.ReadDwgFile(path, System.IO.FileShare.Read, true, "");
}
catch (System.Exception ex)
{
if (ex.Message == "eFileSharingViolation")
{
MessageBox.Show("The X-ref file is open,please close it and try again.");
return;
}
}
//using (Transaction trX = dbase.TransactionManager.StartTransaction())
//{ if you use this replacing the tr below w/ trX the xref doesn't reload
BlockTable btx = tr.GetObject(dbase.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord xModelSpace = tr.GetObject
(btx[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
dbase.WblockCloneObjects(ids, xModelSpace.ObjectId,
new IdMapping(), DuplicateRecordCloning.Replace, false);
dbase.CloseInput(true);
dbase.SaveAs(path, DwgVersion.Current);
db.ReloadXrefs(new ObjectIdCollection(new ObjectId[] { Xref.ObjectId }));
//}
foreach (ObjectId id in ids)
{
Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;
ent.ColorIndex = 1;
ent.Erase();
}
tr.Commit();
}
-
Hey Bryco Just wanted to let you know that you nailed it and I appreciate that.
Researching the docs I was going about it totally different and was getting nowhere with it
again Thanks
I will rearrange the code with transfromation and post later
-
Thanks to Bryco heres the code Let me know if you need a vb version
[CommandMethod("SendToXref")]
public static void SendToXref()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
List<ObjectId> objectsIdsErase = new List<ObjectId>();
PromptEntityOptions peo = new PromptEntityOptions("\nSelect Viewport");
peo.SetRejectMessage("\nNot a Viewport");
peo.AddAllowedClass(typeof(Viewport), true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Viewport vp = (Viewport)tr.GetObject(per.ObjectId, OpenMode.ForRead);
Matrix3d PsToMsTransForm = PaperToModel(vp);
BlockTable bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
BlockTableRecord xrefBtr = (BlockTableRecord)bt["XrefTest"].GetObject(OpenMode.ForRead);
string xPath = xrefBtr.PathName;
PromptSelectionOptions pso = new PromptSelectionOptions();
PromptSelectionResult psr = ed.GetSelection();
if (psr.Status != PromptStatus.OK)
return;
ObjectIdCollection xrefOID = new ObjectIdCollection();
foreach (ObjectId id in psr.Value.GetObjectIds())
{
Entity psEnt = (Entity)tr.GetObject(id, OpenMode.ForWrite);
objectsIdsErase.Add(psEnt.ObjectId);
psEnt.TransformBy(PsToMsTransForm);
xrefOID.Add(psEnt.ObjectId);
}
Database xrefDB = new Database(false, false);
xrefDB.ReadDwgFile(xPath, System.IO.FileShare.Read, true, "");
BlockTable btx = tr.GetObject(xrefDB.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord xModelSpace = tr.GetObject
(btx[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
xrefDB.WblockCloneObjects(xrefOID, xModelSpace.ObjectId,
new IdMapping(), DuplicateRecordCloning.Replace, false);
xrefDB.CloseInput(true);
xrefDB.SaveAs(xPath, DwgVersion.Current);
db.ReloadXrefs(new ObjectIdCollection(new ObjectId[] { xrefBtr.ObjectId }));
tr.Commit();
}
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
BlockTableRecord btrPaper = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.PaperSpace], (OpenMode.ForWrite));
foreach (ObjectId id in btrPaper)
{
if (objectsIdsErase.Contains(id))
{
Entity ent = (Entity)id.GetObject(OpenMode.ForWrite);
ent.Erase();
}
}
tr.Commit();
}
}
private static Matrix3d PaperToModel(Viewport vp)
{
Matrix3d mx = ModelToPaper(vp);
return mx.Inverse();
}
private static Matrix3d ModelToPaper(Viewport vp)
{
Vector3d vd = vp.ViewDirection;
Point3d vc = new Point3d(vp.ViewCenter.X, vp.ViewCenter.Y, 0);
Point3d vt = vp.ViewTarget;
Point3d cp = vp.CenterPoint;
double ta = -vp.TwistAngle;
double vh = vp.ViewHeight;
double height = vp.Height;
double width = vp.Width;
double scale = vh / height;
double lensLength = vp.LensLength;
Vector3d zaxis = vd.GetNormal();
Vector3d xaxis = Vector3d.ZAxis.CrossProduct(vd);
Vector3d yaxis;
if (!xaxis.IsZeroLength())
{
xaxis = xaxis.GetNormal();
yaxis = zaxis.CrossProduct(xaxis);
}
else if (zaxis.Z < 0)
{
xaxis = Vector3d.XAxis * -1;
yaxis = Vector3d.YAxis;
zaxis = Vector3d.ZAxis * -1;
}
else
{
xaxis = Vector3d.XAxis;
yaxis = Vector3d.YAxis;
zaxis = Vector3d.ZAxis;
}
Matrix3d pcsToDCS = Matrix3d.Displacement(Point3d.Origin - cp);
pcsToDCS = pcsToDCS * Matrix3d.Scaling(scale, cp);
Matrix3d dcsToWcs = Matrix3d.Displacement(vc - Point3d.Origin);
Matrix3d mxCoords = Matrix3d.AlignCoordinateSystem(Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis, Point3d.Origin,
xaxis, yaxis, zaxis);
dcsToWcs = mxCoords * dcsToWcs;
dcsToWcs = Matrix3d.Displacement(vt - Point3d.Origin) * dcsToWcs;
dcsToWcs = Matrix3d.Rotation(ta, zaxis, vt) * dcsToWcs;
Matrix3d perspectiveMx = Matrix3d.Identity;
if (vp.PerspectiveOn)
{
double vSize = vh;
double aspectRatio = width / height;
double adjustFactor = 1.0 / 42.0;
double adjstLenLgth = vSize * lensLength * Math.Sqrt(1.0 + aspectRatio * aspectRatio) * adjustFactor;
double iDist = vd.Length;
double lensDist = iDist - adjstLenLgth;
double[] dataAry = new double[] {1,0,0,0,0,1,0,0,0,0,
(adjstLenLgth-lensDist)/adjstLenLgth,lensDist*(iDist-adjstLenLgth)/adjstLenLgth,
0,0,-1.0/adjstLenLgth,iDist/adjstLenLgth};
perspectiveMx = new Matrix3d(dataAry);
}
Matrix3d finalMx = pcsToDCS.Inverse() * perspectiveMx * dcsToWcs.Inverse();
return finalMx;
}
-
Thanks fro, I was hoping someone could explain the transaction problems I show as they don't make a lot of sense.
-
Bryce,
There was no trX.Commit() call in your code.
-
OOPS. Thanx
-
Does that fix your transaction issues?
-
The first or outermost transaction musted be commited for all of the actions in nested transaction to be applied.
//using (Transaction tr = db.TransactionManager.StartTransaction())
//{ if you use this transaction nothing works
AddPaperspaceToXref(ids, "1");
//}
There are nested transaction in the AddPaperspaceToXref method so for them to be applied
using (Transaction tr = db.TransactionManager.StartTransaction())
{
AddPaperspaceToXref(ids, "1");
tr.Commit();
}
Now they will be applied
-
Correct. I was waiting to see if someone spotted that :)