tags:: DXF-Internals

- # Proxy Graphic in DXF Binary Chunk Interpretation
	- Source:
		- [[AutoCAD DevBlog]]: [proxy-graphic-in-dxf-binary-chunk-interpretation.html](https://adndevblog.typepad.com/autocad/2013/02/proxy-graphic-in-dxf-binary-chunk-interpretation.html)
		- Author: [Fenton Webb](https://adndevblog.typepad.com/autocad/fenton-webb.html)
		  id:: 6551c8c7-b9c9-441d-b28c-97e46cdbdc2e
		- Read the comments!
- # Issue
	- How to interpret the [[ProxyGraphic]] binary data enclosed in AutoCAD DXF files?
	-
- # Solution
	- Binary Data enclosed in DXF file is stored by block of 256 bytes maximum under DXF code 310 (i.e. 'kDxfBinaryChunk').
	- A complete description of all standard binary chunks is available in dxf binary chunk interpretation as this one will only describe the proxy graphics binary chunk.
	-
	- ### DXF ENTITY
		- Proxy graphics section is present for all non-AutoCAD core entities (i.e. custom entities, or AutoCAD entities defined in ARX/DBX modules).
		- It is always preceded by a DXF code 92 (of type 'int') which indicates the length of the binary chunk which follow.
		- The binary chunk block contains the proxy graphics generated by the entity, when
		  its 'saveAs()' method was called by AutoCAD upon the DXFOUT command call, as
		  well as some non graphical information which are related to the graphic such as
		  the bounding box, color used, etc....
		- The 'saveAs()' method may call the 'worldDraw()' method which generates the
		  graphic. In case 'worldDraw()' return 'false', the system calls 'viewporDraw()'
		  to generate the viewport dependent graphic.
		- It means the proxy graphic binary chunk contains the graphic primitive calls representation called during worldDraw() or viewportDraw().
		- Finally the proxy graphic binary chunk is the same thing as a Windows Metafile.
		- Instead of containing an image, it contains the instruction to redraw the last representation generated by worldDraw()/viewportDraw().
		- Depending of the settings of AutoCAD (i.e. Proxy Graphic Never Saved), and the
		  presence of the ARX/DBX module when the DXFOUT operation occurred, the proxy
		  graphics binary chunk can contain:
			- a bounding box with class name and logical application name,
			- the last know entity graphic description.
		- As said above the proxy graphics binary chunk contains just an output of the AcGiWorldDraw/AcGiViewportDraw vector collector classes which were called upon
		  DXFOUT.
		- The proxy graphics binary chunk' output is of form:
		- ```
		  {Header}[{Command} [{Command} [{Command} [...]]]]
		  ```
		- and the {Command} packet is of form:
			- ```
			  {Command Packet Length} {Command OPCODE} [{Command Argument} {Command argument} ...]
			  ```
		- To interpret the output of the {Header}, apply the following rule:
		  ```
		  {Header}
		  {int32 / Length of the binary chunk} {int32 / Number of commands}
		  ```
		- To Interpret a {Command} packet, apply the following rules:
		  ```
		  {Command}
		  {int 32 / Command Packet Length} {int 32 / Command OPCODE} [{Command
		  Argument} {Command argument} ...]
		  
		  {Command Argument}
		  ```
		- The command argument(s) depends of the OPCODE, see below for more information.
	- ### OPCODE=0 (kAcGiOpBad)
		- ```
		  <No AcGiGeometry Primitive Equivalent>
		  ```
		- Should not happen.
		- If it does, skip to packet length.
		- This has been provide for backward compatibility for r13/r14 reading AutoCAD 2000 DXF file for example.
		- ```
		  {Nothing}
		  ```
	- ### OPCODE=1 (kAcGiOpSetExtents)
		- ```
		  <No AcGiGeometry Primitive Equivalent>
		  ```
		- This one define an extent, by providing two 3D points.
		- ```
		  {AcGePoint3d / Min. point} {AcGePoint3d / Max. point}
		  ```
	- ### OPCODE=2 (kAcGiOpCircle1)
		- ```
		  <acgigeometry:: circle (const AcGePoint3d& center, const double radius, const AcGeVector3d &normal)>
		  ```
		- Displays a circle primitive with center and a radius.
		- ```
		  {AcGePoint3d / Center} {double / Radius} {AcGeVector3d / Normal}
		  ```
	- ### OPCODE=3 (kAcGiOpCircle2)
		- ``` 
		  <AcGiGeometry::circle (const AcGePoint3d& pt1, const AcGePoint3d& pt2, const AcGePoint3d& pt3)>
		  ```
		- Displays a circle primitive that is defined by the three points--pt1, pt2, and pt3--which all lie on the circle.
		- `{AcGePoint3d / 1st point} {AcGePoint3d / 2nd point} {AcGePoint3d / 3rdt point}`
	- ### OPCODE=4 (kAcGiOpCircularArc1)
		- ```
		  <AcGiGeometry::circularArc (const AcGePoint3d& center, const double radius,
		  const AcGeVector3d& normal, const AcGeVector3d& startVector, const double
		  sweepAngle, const AcGiArcType arcType)>
		  ```
		- Displays an arc primitive defined by the arc's center of curvature center, the radius of curvature radius, the containment plane's normal vector normal, the vector from the center of curvature to the arc start point startVector, the angle that the arc spans sweepAngle, and the arc type arcType.
		- ```
		  {AcGePoint3d / Center} {double / Radius} {AcGeVector3d / Normal} {AcGeVector3d
		  / Start vector} {double / Angle} {int32 / Arc type}
		  ```
	- ### OPCODE=5 (kAcGiOpCircularArc2)
		- ```
		  <AcGiGeometry::circularArc (const AcGePoint3d& start, const AcGePoint3d&
		  point, const AcGePoint3d& end, const AcGiArcType arcType)>
		  ```
		- Displays an arc primitive defined by the three points.
		- ```
		  {AcGePoint3d / 1st point} {AcGePoint3d / 2nd point} {AcGePoint3d / 3rdt point}
		  {int32 / Arc type}
		  ```
	- ### OPCODE=6 (kAcGiOpPolyline)
		- ```
		  <AcGiGeometry::polyline (const Adesk::UInt32 nbPoints, const AcGePoint3d*
		  pVertexList, const AcGeVector3d* pNormal, Adesk::Int32 lBaseSubEntMarker)>
		  ```
		- Draws a polyline.
		- ```
		  {int32 / Number of vertex} {AcGePoint3d / Vertex} [{AcGePoint3d / Vertex}
		  [...]]
		  ```
	- ### OPCODE=7 (kAcGiOpPolygon)
		- ```
		  <AcGiGeometry::polygon (const Adesk::UInt32 nbPoints, const AcGePoint3d* pVertexList)>
		  ```
		- Draws a polygon.
		- ```
		  {int32 / Number of vertex} {AcGePoint3d / Vertex} [{AcGePoint3d / Vertex}
		  [...]]
		  ```
	- ### OPCODE=8 (kAcGiOpMesh)
		- ```
		  <AcGiGeometry::mesh (const Adesk::UInt32 rows, const Adesk::UInt32 columns,
		  const AcGePoint3d* pVertexList, const AcGiEdgeData* pEdgeData, const
		  AcGiFaceData* pFaceData, const AcGiVertexData* pVertexData)>
		     ```
		- Draws a mesh.
		- ```
		  {int32 / Number of rows} {int32 / Number of columns} {Vertex List} {Edge Data
		  Packet} {Face Data Packet} {Vertex Data Packet}
		  ```
		- Number of Vertexes: `{Number of rows} * {Number of columns}`
		- Number of Edges: `2 * {Number of Vertexes} - {Number of rows} - {Number of columns}`
		- Number of Faces: `({Number of rows} - 1) * ({Number of columns} - 1)`
		- ```
		  {Vertext List}
		  {AcGepoint3d / Vertex} [{AcGepoint3d / Vertex} [...]]
		  
		  {Edge Data Packet}
		  {int32 / Edge info type} {Edge data}
		  ```
		- 'Edge info type' is a bitwise value which indicates what are the data behind.
		- NB: 'Edge data' stored are order dependant.
		- Bit values:
			- ACGI_COLORS (0x01),
			- ACGI_LAYER_IDS (0x100),
			- ACGI_LINETYPE_IDS(0x200),
			- ACGI_MARKERS (0x20),
			- ACGI_VIS_DATA (0x40)
		- ```
		  {Edge data}
		  ACGI_COLORS <array of 'short int'>
		  {int16 / Color index} [{int16 / Color index} [...]]
		  ACGI_LAYER_IDS <array of 'id'>
		  {AcDbHardPointerId / Layer ID} [{AcDbHardPointerId / Layer ID} [...]]
		  ACGI_LINETYPE_IDS <array of 'id'>
		  {AcDbHardPointerId / Linetype ID} [{AcDbHardPointerId / Linetype ID}
		  [...]]
		  ACGI_COLORS <array of 'int'>
		  {int32 / ACGI marker} [{int32 / ACGI marker} [...]]
		  ACGI_VIS_DATA <array of 'Adesk::Boolean'>
		  {int8 / Visibilit flag} [{int8 / Visibilit flag} [...]]
		  
		  {Face Data Packet}
		  {int32 / Face info type} {Face data}
		  ```
		- 'Face info type' is a bitwise value which indicates what are the data behind.
		- NB: 'Face data' stored are order dependant.
		- Bit values:
			- ACGI_COLORS (0x01),
			- ACGI_LAYER_IDS (0x100),
			- ACGI_MARKERS (0x20),
			- ACGI_NORMALS (0x80),
			- ACGI_VIS_DATA (0x40)
		- ```
		  {Face data}
		  ACGI_COLORS <array of 'short int'>
		  {int16 / Color index} [{int16 / Color index} [...]]
		  ACGI_LAYER_IDS <array of 'id'>
		  {AcDbHardPointerId / Layer ID} [{AcDbHardPointerId / Layer ID} [...]]
		  ACGI_COLORS <array of 'int'>
		  {int32 / ACGI marker} [{int32 / ACGI marker} [...]]
		  ACGI_NORMALS <array of 'AcGeVector3d'>
		  {AcGeVector3d / Normal} [{AcGeVector3d / Normal} [...]]
		  ACGI_VIS_DATA <array of 'Adesk::Boolean'>
		  {int8 / Visibilit flag} [{int8 / Visibilit flag} [...]]
		  
		  {Vertex Data Packet}
		  {int32 / Vertex info type} {Vertex data}
		  ```
		- 'Vertex info type' is a bitwise value which indicates what are the data
		  behind.
		- NB: 'Vertex data' stored are order dependant.
			- Bit values:
			- ACGI_NORMALS (0x80),
			- ACGI_ORIENTATION (0x400)
		- ```
		  {Vertex data}
		  ACGI_NORMALS <array of 'AcGeVector3d'>
		  {AcGeVector3d / Normal} [{AcGeVector3d / Normal} [...]]
		  ACGI_ORIENTATION <array of 'int'>
		  {int32 / AcGiOrientationType} [{int32 / AcGiOrientationType} [...]]
		  ```
	- ### OPCODE=9 (kAcGiOpShell)
		- ```
		  <AcGiGeometry::shell (const Adesk::UInt32 nbVertex, const AcGePoint3d*
		  pVertexList, const Adesk::UInt32 faceListSize, const Adesk::Int32* pFaceList,
		  const AcGiEdgeData* pEdgeData, const AcGiFaceData* pFaceData, const
		  AcGiVertexData* pVertexData, const resbuf* pResBuf)>
		  ```
		- Draws a shell.
		- ```
		  {int32 / Number of vertexes} {Vertex List} {int32 / Face list size} {Face
		  list} {Edge Data Packet} {Face Data Packet} {Vertex Data Packet}
		  
		  {Vertext List}
		  {AcGepoint3d / Number of vertex} [{AcGepoint3d / Vertex} [...]]
		  
		  {Face list}
		  {int32 / Face vertex count} {int32 / Vertex indice} [{int32 / Vertex indice}
		  [...]]
		  
		  {Edge Data Packet}
		  ```
		- See mesh definition above.
		- ```
		  {Face Data Packet}
		  See mesh definition above.
		  
		  {Vertex Data Packet}
		  ```
		- See mesh definition above.
	- ### OPCODE=10 (kAcGiOpText1)
		- ```
		  <AcGiGeometry::text (const AcGePoint3d& position, const AcGeVector3d& normal,
		  const AcGeVector3d& direction, const double height, const double width, const
		  double oblique, const char* pMsg)>
		  ```
		- Draws a text.
		- ```
		  {AcGePoint3d / Position} {AcGeVector3d / Normal} {AcGeVector3d / Direction}
		  {double / Height} {double / Widht} {double / Oblique} {char * / Text string}
		  ```
	- ### OPCODE=11 (kAcGiOpText2)
		- ```
		  <AcGiGeometry::text (const AcGePoint3d& position, const AcGeVector3d& normal,
		  const AcGeVector3d& direction, const char* pMsg, const Adesk::Int32 length,
		  const Adesk::Boolean raw, const AcGiTextStyle& pTextStyle)>
		  ```
		- Draws a text.
		- ```
		  {AcGePoint3d / Position} {AcGeVector3d / Normal} {AcGeVector3d / Direction}
		  {char * / Text string} {int32 / length} {int32 / Raw code} {double / Text size}
		  {double / Xscale} {double / Obliquing angle} {double / Tracking percentage}
		  {int32 / IsBackward} {int32 / IsUpsideDown} {int32 / IsVertical} {int32 /
		  IsUnderlined} {int32/ IsOverlined} {char * / Font name} {char * / Big font name}
		  ```
	- ### OPCODE=12 (kAcGiOpXLine)
		- ```
		  <AcGiGeometry::xline(const AcGePoint3d& oneXlinePoint, const AcGePoint3d&
		  aDifferentXlinePoint)>
		  ```
		- An xline passing '1st point' and a '2nd point' is displayed.
		- ```
		  {AcGePoint3d / 1st point} {AcGePoint3d / 2nd point}
		  ```
	- ### OPCODE=13 (kAcGiOpRay)
		- ```
		  <AcGiGeometry::ray (const AcGePoint3d& raysStartingPoint, const AcGePoint3d&
		  aDifferentRayPoint)>
		  ```
		- Displays a ray that starts at '1st point' and passes through a '2nd point'.
		- `{AcGePoint3d / 1st point} {AcGePoint3d / 2nd point}`
	- ## OPCODE=14 (kAcGiOpColor)
		- ```
		  <AcGiSubEntityTraits::setColor (const Adesk::UInt16 color)>
		  {unsigned int32 / Color index}
		  ```
	- ### OPCODE=15 (kAcGiOpLayerName)
		- ```
		  <AcGiSubEntityTraits::setLayer (const AcDbObjectId layerId)>
		  {char * / Layer name}
		  ```
	- ## OPCODE=16 (kAcGiOpLayerIndex)
		- ```
		  <AcGiSubEntityTraits::setLayer (const AcDbObjectId layerId)>
		  {AcDbHardPointerId / Layer ID}
		  ```
	- ### OPCODE=17 (kAcGiOpLineTypeName)
		- ```
		  <AcGiSubEntityTraits::setLineType (const AcDbObjectId linetypeId)>
		  {char * / Linetype name}
		  ```
	- ### OPCODE=18 (kAcGiOpLineTypeIndex)
		- ```
		  <AcGiSubEntityTraits::setLineType (const AcDbObjectId linetypeId)
		  {AcDbHardPointerId / Linetype ID}
		  ```
	- ### OPCODE=19 (kAcGiOpSelectionMarker)
		- ```
		  <AcGiSubEntityTraits::setSelectionMarker (const Adesk::Int32 markerId)>
		  {unsigned int32 / ACGI marker}
		  ```
	- ### OPCODE=20 (kAcGiOpFillType)
		- ```
		  <AcGiSubEntityTraits::setFillType (const AcGiFillType fill)>
		  {unsigned int32 / AcGiFillType}
		  ```
	- ### OPCODE=21 (kAcGiBoundingBoxSave)
		- ```
		  <No AcGiGeometry Primitive Equivalent>
		  {Nothing}
		  ```
		-
	- # New ones for Tahoe
	- ### OPCODE=22 (kAcGiOpTrueColor)
		- ``` 
		  <AcGiSubEntityTraits::setTrueColor (const AcCmEntityColor& color)>
		  {AcCmEntityColor / True color definition}
		  ```
	- ### OPCODE=23 (kAcGiOpLineWeight)
		- ```
		  <AcGiSubEntityTraits::setLineWeight (const AcDb::LineWeight lw)>
		  {double / Lineweight}
		  ```
	- ### OPCODE=24 (kAcGiOpLineTypeScale)
		- ```
		  <AcGiSubEntityTraits::setLineTypeScale (double dScale)>
		  {double / Line scale}
		  ```
	- ### OPCODE=25 (kAcGiOpThickness)
		- ```
		  <AcGiSubEntityTraits::setThickness (double dThickness)>
		  {double/ Thickness}
		  ```
	- ### OPCODE=26 (kAcGiOpPlotStyleName)
		- ```
		  <AcGiSubEntityTraits::setPlotStyleName (AcDb::PlotStyleNameType type, const
		  AcDbObjectId & id)>
		  {int32 / PlotStyle name type} {int32 / ID}
		  ```
	- ### OPCODE=27 (kAcGiOpPushClipBoundary)
		- ```
		  <AcGiGeometry::pushClipBoundary (AcGiClipBoundary* pBoundary)>
		  {AcGiClipBoundary / Clip Boundary}
		  ```
		- ```C
		  struct AcGiClipBoundary {
		    // Boundaries
		    AcGeVector3d    m_vNormal;
		    AcGePoint3d     m_ptPoint;
		    AcGePoint2dArray    m_aptPoints;
		  
		    // Transforms
		    AcGeMatrix3d    m_xToClipSpace;
		    AcGeMatrix3d    m_xInverseBlockRefXForm;
		  
		    // Z clipping
		    Adesk::Boolean    m_bClippingFront;
		    Adesk::Boolean    m_bClippingBack;
		    double        m_dFrontClipZ;
		    double        m_dBackClipZ;
		  
		    Adsk::Boolean    m_bDrawBoundary;
		  };
		  ```
	- ### OPCODE=28 (kAcGiOpPopClipBoundary)
		- ```
		  <AcGiGeometry::popClipBoundary ()>
		  {Nothing}
		  ```
	- ### OPCODE=29 (kAcGiOpPushTransformM)
		- ```
		  <No AcGiGeometry Primitive Equivalent>
		  {AcGeMatrix3d / Matrix}
		  ```
	- ### OPCODE=30 (kAcGiOpPushTransformV)
		- ```
		   <No AcGiGeometry Primitive Equivalent>
		   {AcGeMatrix3d/ Matrix}
		  ```
	- ### OPCODE=31 (kAcGiOpPopTransform)
		- ```
		  <No AcGiGeometry Primitive Equivalent>
		  {Nothing}
		  ```
	- ### OPCODE=32 (kAcGiOpPlineNormal)
		- ```
		  <AcGiViewportGeometry::polylineEye (const Adesk::UInt32 nbPoints, const
		  AcGePoint3d* pPoints)
		  AcGiViewportGeometry::polylineDc (const Adesk::UInt32 nbPoints, const
		  AcGePoint3d* pPoints)>
		  
		  {int32 / Number of points} {AcGePoint3d / Point definition} [{AcGePoint3d /
		  Point definition} [...]] {AcGeVector3d / Normal}
		  ```
	- ### OPCODE=33 (kAcGiOpMaxOpCodes)
		- `<No AcGiGeometry Primitive Equivalent>`
		- Should not happen.
		- If it does, skip to packet length.
		- This has been provided for forward compatibility for r2000 reading later AutoCAD releases DXF file for example.