Creating associative dimension in paperspace associated to a modelspace entity

<?xml encoding=”UTF-8″>By Balaji Ramamoorthy

Most of the code in this blog post is from a code snippet that my colleague Philippe Leefsma implemented. While his original code created an aligned dimension in paperspace, i have modified it slightly to create an ordinate dimension to cater to a recent developer request.

Here are the code snippets to create aligned and ordinate dimensions in paperspace while retaining their associativity with a reference point on an entity that is in modelspace.

 <span>//For AcDbDimAssoc</span><span> </span>
 <span>#include</span><span>  <span>"dbdimassoc.h"</span><span>  </span></span>
 
 <span>//For AcDbOsnapPointRef</span><span> </span>
 <span>#include</span><span>  <span>"dbdimptref.h"</span><span> </span></span>
 
 <span>static</span><span>  <span>void</span><span>  paperRotatedDimAssoc(<span>void</span><span> )</span></span></span>
 <span>{</span>
 	AcDbDatabase* pDb 
 		= acdbHostApplicationServices()->workingDatabase();
 
 	AcDbBlockTableRecordPointer ms(
 		ACDB_MODEL_SPACE, pDb, AcDb::kForWrite);
 
 	AcDbBlockTableRecordPointer ps(
 		ACDB_PAPER_SPACE, pDb, AcDb::kForWrite);
 
 	AcDbObjectId lineId, vpId, dimId;
 
 	AcGePoint3d pt1(AcGePoint3d::kOrigin);
 	AcGePoint3d	pt2(5,0,0);
 
 	<span>{</span><span>//creates a line</span><span> </span>
 		AcDbObjectPointer<AcDbLine> line;
 		line.create();
 		line->setStartPoint(pt1);
 		line->setEndPoint(pt2);
 		ms->appendAcDbEntity(lineId, line);
 	<span>}</span>
 
 	<span>{</span><span>//creates a viewport</span><span> </span>
 		AcDbObjectPointer<AcDbViewport> vp;
 		vp.create();
 		ps->appendAcDbEntity(vpId, vp);
 		vp->setWidth(10);
 		vp->setHeight(10);
 		vp->setCenterPoint(AcGePoint3d(5,5,0));
 
 		vp->setViewDirection(AcDb::kTopView);
 		vp->setViewTarget(AcGePoint3d(2.5,0,0));
 		vp->setViewCenter(AcGePoint2d(2.5,0));
 		vp->setUnlocked();
 		vp->setOn();
 
 		AcGeMatrix3d ms2ps(
 			AcDbPointRef::mswcsToPswcs(vp));
 		pt1 = pt1.transformBy(ms2ps);
 		pt2 = pt2.transformBy(ms2ps);
 	<span>}</span>
 
 	<span>{</span><span>//creates the dimension object</span><span> </span>
 		AcDbObjectPointer<AcDbRotatedDimension> dim;
 		dim.create();
 		dim->setXLine1Point(pt1);
 		dim->setXLine2Point(pt2);
 		dim->setDimLinePoint(AcGePoint3d(2,2,0));
 		ps->appendAcDbEntity(dimId, dim);
 	<span>}</span>
 
 	AcDbObjectPointer<AcDbDimAssoc> assoc;
 	assoc.create();
 
 	AcDbObjectIdArray arr(2);
 	arr.append(vpId);
 	arr.append(lineId);
 
 	AcDbFullSubentPath path1(
 		arr, 
 		AcDbSubentId(AcDb::kVertexSubentType, 0));
 
 	AcDbFullSubentPath path2(
 		arr, 
 		AcDbSubentId(AcDb::kVertexSubentType, 1));
 
 	AcGePoint3d refPt1(pt1);
 	AcDbOsnapPointRef *ref1 = <span>new</span><span>  AcDbOsnapPointRef(</span>
 		AcDbPointRef::kOsnapNear, &path1, &path1, &refPt1);
 
 	AcGePoint3d refPt2(pt2);
 	AcDbOsnapPointRef *ref2 = <span>new</span><span>  AcDbOsnapPointRef(</span>
 		AcDbPointRef::kOsnapNear, &path2, &path2, &refPt2);
 
 	assoc->setDimObjId(dimId);
 	assoc->setTransSpatial(<span>true</span><span> );</span>
 	assoc->setPointRef(AcDbDimAssoc::kXline1Point, ref1);
 	assoc->setPointRef(AcDbDimAssoc::kXline2Point, ref2);
 	assoc->setAssocFlag(<span>static_cast</span><span> <<span>int</span><span> >(</span></span>
 		AcDbDimAssoc::kFirstPointRef
 		|AcDbDimAssoc::kSecondPointRef));
 
 	assoc->updateDimension();
 
 	AcDbObjectId dimAssocId;
 	Acad::ErrorStatus es = acdbPostDimAssoc(
 		dimId, assoc, dimAssocId);
 
 	acutPrintf(_T(<span>"\npost dim: %s\n"</span><span> ), </span>
 		acadErrorStatusText(es));
 
 	<span>if</span><span>  (assoc.open(dimAssocId, AcDb::kForWrite)</span>
 		==Acad::eOk)
 	<span>{</span>
 		assoc->startCmdWatcher();
 		assoc->addToPointRefReactor();
 		assoc->addToDimensionReactor();
 	<span>}</span>
 <span>}</span>
 
 <span>static</span><span>  <span>void</span><span>  paperOrdinateDimAssoc(<span>void</span><span> )</span></span></span>
 <span>{</span>
 	AcDbDatabase* pDb 
 		= acdbHostApplicationServices()->workingDatabase();
 
 	AcDbBlockTableRecordPointer ms(
 		ACDB_MODEL_SPACE, pDb, AcDb::kForWrite);
 	
 	AcDbBlockTableRecordPointer ps(
 		ACDB_PAPER_SPACE, pDb, AcDb::kForWrite);
 
 	AcDbObjectId lineId, vpId, dimId;
 
 	AcGePoint3d pt1(AcGePoint3d::kOrigin);
 	AcGePoint3d	pt2(5,0,0);
 
 	<span>{</span><span>//creates a line</span><span> </span>
 		AcDbObjectPointer<AcDbLine> line;
 		line.create();
 		line->setStartPoint(pt1);
 		line->setEndPoint(pt2);
 		ms->appendAcDbEntity(lineId, line);
 	<span>}</span>
 
 	<span>{</span><span>//creates a viewport</span><span> </span>
 		AcDbObjectPointer<AcDbViewport> vp;
 		vp.create();
 		ps->appendAcDbEntity(vpId, vp);
 		vp->setWidth(10);
 		vp->setHeight(10);
 		vp->setCenterPoint(AcGePoint3d(5,5,0));
 
 		vp->setViewDirection(AcDb::kTopView);
 		vp->setViewTarget(AcGePoint3d(2.5,0,0));
 		vp->setViewCenter(AcGePoint2d(2.5,0));
 		vp->setUnlocked();
 		vp->setOn();
 
 		AcGeMatrix3d ms2ps(
 			AcDbPointRef::mswcsToPswcs(vp));
 		pt1 = pt1.transformBy(ms2ps);
 		pt2 = pt2.transformBy(ms2ps);
 	<span>}</span>
 
 	<span>{</span><span>//creates the dimension object</span><span> </span>
 		AcDbObjectPointer<AcDbOrdinateDimension> dim;
 		dim.create();
 		dim->setUsingXAxis(<span>true</span><span> );</span>
 		dim->setOrigin(pt1);
 		dim->setDefiningPoint(pt2);
 		dim->setLeaderEndPoint(pt2 
 			+ AcGeVector3d(1.0, 0.0, 0.0));
 		ps->appendAcDbEntity(dimId, dim);
 	<span>}</span>
 
 	AcDbObjectPointer<AcDbDimAssoc> assoc;
 	assoc.create();
 
 	AcDbObjectIdArray arr(2);
 	arr.append(vpId);
 	arr.append(lineId);
 
 	AcDbFullSubentPath path1(
 		arr, 
 		AcDbSubentId(AcDb::kVertexSubentType, 0));
 
 	AcDbFullSubentPath path2(
 		arr,
 		AcDbSubentId(AcDb::kVertexSubentType, 1));
 
 	AcGePoint3d refPt1(pt1);
 	AcDbOsnapPointRef *ref1 = <span>new</span><span>  AcDbOsnapPointRef(</span>
 		AcDbPointRef::kOsnapNear, &path1, &path1, &refPt1);
 
 	AcGePoint3d refPt2(pt2);
 	AcDbOsnapPointRef *ref2 = <span>new</span><span>  AcDbOsnapPointRef(</span>
 		AcDbPointRef::kOsnapNear, &path2, &path2, &refPt2);
 
 	assoc->setDimObjId(dimId);
 	assoc->setTransSpatial(<span>true</span><span> );</span>
 	assoc->setPointRef(AcDbDimAssoc::kOriginPoint, ref1);
 	assoc->setPointRef(AcDbDimAssoc::kDefiningPoint, ref2);
 	assoc->setAssocFlag(<span>static_cast</span><span> <<span>int</span><span> >(</span></span>
 		AcDbDimAssoc::kFirstPointRef|
 		AcDbDimAssoc::kSecondPointRef));
 
 	assoc->updateDimension();
 
 	AcDbObjectId dimAssocId;
 	Acad::ErrorStatus es = 
 		acdbPostDimAssoc
 		(dimId, assoc, dimAssocId);
 
 	acutPrintf(_T(<span>"\npost dim: %s\n"</span><span> ), </span>
 		acadErrorStatusText(es));
 
 	<span>if</span><span>  (assoc.open(dimAssocId, AcDb::kForWrite)==Acad::eOk)</span>
 	<span>{</span>
 		assoc->startCmdWatcher();
 		assoc->addToPointRefReactor();
 		assoc->addToDimensionReactor();
 	<span>}</span>
 <span>}</span>
 


Comments

6 responses to “Creating associative dimension in paperspace associated to a modelspace entity”

  1. Hi Balaji,
    What about the new assoc dimensions based on AcDbAssocPersSubentId (http://adndevblog.typepad.com/autocad/2015/02/making-a-custom-entity-associative-dimension-enabled.html) ?
    I have some issues to make my custom compound entities compatible with this new behavior and I think having a sample similar to yours but using the new behaviour would help me to understand how it works.
    Thanks!
    Loic

  2. Hi Loic,
    Sorry for the delay in replying to you. I had taken a day off last Friday.
    I will look into the sample that you shared and see how we can get it to work with the AcdbAssocPersSubentId.
    I will get back to you on this.
    Regards,
    Balaji

  3. Thanks a lot!
    (No worry for the delay, there’s no rush here, I hope you enjoyed your Friday!)

  4. Abhay Joshi Avatar
    Abhay Joshi

    do we need to delete AcDbOsnapPointRef instance?

  5. Hello Balaji,
    I am trying to create the associative dimension in paper space same as example. As per your sample code, it works well for top viewport with scale 1:1. But creates issues for dimensions in isometric views with scale other than 1:1. Before creating AcDbDimAssoc object. I override DIMLFAC for dimension by using setDimlfac(). Which include scale (1.22 * 10). It dimension showed correct value after creating it. But after I changed view scale manually, the value is no longer correct.
    After checking difference between manual and programmatic dimension in ArxDbg, I found XDATA for ACAD_DIMASSOC_CALC_DIMLFAC, ACAD_DIMASSOC_DIMLFAC and ACAD_DIMASSOC_OVERRIDDEN_DIMLFAC in manual dimensions.
    After googling I found link https://forums.autodesk.com/t5/autocad-2000-2000i-2002-archive/paperspace-dimensions-giving-incorrect-values/m-p/141420 for DIMLFAC XDATA. I mentioned to set XDATA for these applications.
    In code after creating AcDbDimAssoc I set XDATA to dimension for ACAD_DIMASSOC_OVERRIDDEN_DIMLFAC with lfac*viewscale and ACAD_DIMASSOC_CALC_DIMLFAC with viewscale.
    Then dimension worked fine for all manual operations (changing viewscale, modification in line).
    Is it safe to set XDATA for DIMLFAC?

  6. Ari Bejarano Avatar
    Ari Bejarano

    Hi Balaji,
    This piece of code does not work for me and I do not know what I’m doing wrong, just draw the line and the text appears:
    \npost dim: eOk\n
    I am using autocad 2018 and ObjectARX 2018, my goal is to do it from .net but I see that it is not yet possible. Could you pass me the complete code, please?

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading