Problem with SetDrawingBoxCAD

Discuss and ask questions about CAD DLL (CAD Image DLL, CAD Importer DLL).

Moderators: admin, support, SDS

Post Reply
marmotMan81
Posts: 1
Joined: 28 May 2008, 21:32

Problem with SetDrawingBoxCAD

Post by marmotMan81 » 28 May 2008, 23:53

I'm trying to break up the would-be CAD image into tiles, but I'm having issues. Ultimately, what I'm doing is convert the image returned from CADImage into an OpenGL texture. Now, I can do this just fine by DrawCADtoBitmap with the full entents of the image, however due to hardware limitations on the graphics card, the quality of the texture is greatly diminished. I can get around those limitations by breaking up the image into smaller tiles - and there are other performance benefits for doing this, too. But, I'm having a hard time getting CADImage to only draw the region that corresponds with an arbitrary tile.

The CADDRAW object passed to DrawCADtoBitmap represents the output dimensions of the image. So, if I want my tile-image to be of size 512x512, then I initialize the CADDRAW.R to be of size 512x512.

Prior to calling DrawCADtoBitmap, I also make a call to SetDrawingBoxCAD, which I thought would restrict drawing of the CAD object to the bounds specified by the FRECT region argument. To initialize that region, I retrieved the extents of the CAD drawing (in CAD space) and then calculated the positioning of each tile - passing the tile positions into SetDrawingBoxCAD.

Sometimes, this works fine. Other times, it doesn't. To try and debug what was going on, I called GetExtentsCAD after the SetDrawingBoxCAD to compare their values. Am I correct in assuming that GetExtentsCAD will get the current drawing region? (the border type is set to 0, and the border size is also set to 0)

What I found from this test was that sometimes the values of the extents after calling SetDrawingBoxCAD were rotated/swapped/negated/etc. Sometimes, even, I was unable to find a particular pattern. But, any time the values were set incorrectly (incorrectly meaning the region I wanted to set didn't actually get set), during draw, the region would revert to the full extents, and thus each tile would be a miniature preview of the full drawing, rather than a particular chunk.

Am I using/interpreting these functions wrong? Is there a work-around?

Here is a sample chunk of my code that I'm using, if it helps any:

Code: Select all

void CMainHandler::LoadSampleCADFile(char *filename)
{
  CADDRAW r;
  FRECT extents;
  float fW, fH;
  double dx, dy;
  double pDx, pDy;
  double xPos, yPos;

  HANDLE CADImage = CreateCAD(NULL, filename);

  nLayouts = CADLayoutsCount(CADImage);
  curLayout = 0;

  if (nLayouts > 0) {
    tex = new PTextureBMP [nLayouts];
    nTilesW = new int [nLayouts];
    nTilesH = new int [nLayouts];
    imgW = new int [nLayouts];
    imgH = new int [nLayouts];
  }

  // generate tiled-textures for each layout
  for (int i = 0; i < nLayouts; i++) {
    // make the current layout active
    CurrentLayoutCAD(CADImage, i, TRUE);

    // get the extents of the full image
    ResetDrawingBoxCAD(CADImage);
    SetCADBorderType(CADImage, 0);
    SetCADBorderSize(CADImage, 0.0);
    GetExtentsCAD(CADImage, &extents);
    GetBoxCAD(CADImage, &fW, &fH);

    pDx = extents.Points.Right - extents.Points.Left;
    pDy = extents.Points.Top - extents.Points.Bottom;

    // determine how many tiles will span the image horizontally and vertically
    imgW[i] = (fW > fH) ? MaxTexDimension() : (int)((double)MaxTexDimension() * (fW / fH));
    imgH[i] = (fH > fW) ? MaxTexDimension() : (int)((double)MaxTexDimension() * (fH / fW));
    
    nTilesW[i] = imgW[i] / TileWidth();
    if (nTilesW[i] * TileWidth() < imgW[i] || nTilesW[i] == 0) nTilesW[i] = nTilesW[i] + 1;
    dx = (pDx / imgW[i]) * TileWidth();

    nTilesH[i] = imgH[i] / TileHeight();
    if (nTilesH[i] * TileHeight() < imgH[i] || nTilesH[i] == 0) nTilesH[i] = nTilesH[i] + 1;
    dy = (pDy / imgH[i]) * TileHeight();

    tex[i] = new CTextureBMP [nTilesW[i] * nTilesH[i]];

    double y0 = extents.Points.Bottom;
    double x0 = extents.Points.Left;

    // cycle through each tile
    yPos = y0;
    for (int j = 0; j < nTilesH[i]; j++) {
      xPos = x0;
      for (int k = 0; k < nTilesW[i]; k++) {
        // determine the CAD-space positioning of each tile
        extents.Points.Top = yPos + dy;
        extents.Points.Left = xPos;
        extents.Points.Right = xPos + dx;
        extents.Points.Bottom = yPos;

        // restrict drawing of CAD object to this tile's region only
        SetDrawingBoxCAD(CADImage, &extents);

        // set the output dimension to the tile size (in pixels)
        r.R.top = 0;
        r.R.left = 0;
        r.R.right = TileWidth();
        r.R.bottom = TileHeight();

        // draw the CAD object and retrieve the memory reference
        HANDLE Hnd = DrawCADtoBitmap(CADImage, &r);

        // parse through the CAD image in memory and generate a texture object from it
        tex[i][(j*nTilesW[i])+k] = CTextureBMP();
        tex[i][(j*nTilesW[i])+k].AssignEmbedded((char *)GlobalLock(Hnd), nTexUnits, GL_TEXTURE_2D);

        // free up the CAD image memory
        GlobalUnlock(Hnd);
        GlobalFree(Hnd);

        // refresh the display to be able to watch progress
        OnDisplay();
        xPos += dx;
      } // for each tile horizontally
      yPos += dy;
    } // for each tile vertically
  } // for each layout
}

Thanks!

- Kyle


PS - I also found that the DrawCADtoDIB function sometimes changed the pixel dimensions of the output image. So, if you wanted it to be for example 1280x1024 (and the aspect ratio of the CAD drawing was also 5:4), sometimes, the DIB generated would be of a completely different aspect ratio. I haven't noticed it when using DrawCADtoBitmap, though - hence why I'm now using that function. But, I wondered if this is a known bug, or if there is actually a valid reason why it is changing the dimensions on me. Thanks again!

support
Posts: 2932
Joined: 30 Mar 2005, 11:36
Contact:

Re: Problem with SetDrawingBoxCAD

Post by support » 29 May 2008, 16:47

Hello!

We have added some code in to a VC demo application from the CADImage.DLL package:
MainWindow.cpp:

Code: Select all

void CMainWindow::SetDrawingBox()
{
	CADDRAW nCADDraw;
	optionsCAD.IsDrawingBox = true;
	if ((CADImage != NULL) && !bIsRotated)
	{		
		rectDrawingBox.Points.Left = (frectExtentsCAD.Points.Left + frectExtentsCAD.Points.Right)/2;
		rectDrawingBox.Points.Top =  frectExtentsCAD.Points.Top;
		rectDrawingBox.Points.Z1 = 0;  
		rectDrawingBox.Points.Right = frectExtentsCAD.Points.Right; 
		rectDrawingBox.Points.Bottom = frectExtentsCAD.Points.Bottom; 
		rectDrawingBox.Points.Z2 = 0; 		
		SetDrawingBoxCAD(CADImage, &rectDrawingBox);

		//RecalculateExtents();

		nCADDraw.Size = sizeof(CADDRAW);
		nCADDraw.DC = 0; 
		nCADDraw.DrawMode = 0;
		nCADDraw.R.left = 0;
		nCADDraw.R.right = 512;
		nCADDraw.R.top = 0;
		nCADDraw.R.bottom = 512;

		HANDLE hDIB = DrawCADtoBitmap(CADImage, &nCADDraw);
		if (hDIB) 
		{
			DWORD Size = GlobalSize(hDIB);
			void *P = GlobalLock(hDIB);
			HANDLE FHnd = CreateFile("c:\\Test.bmp", GENERIC_WRITE, FILE_SHARE_READ,
				NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
			if (FHnd) 
			{
				DWORD Wrt;
				WriteFile(FHnd, P, Size, &Wrt, NULL);
				CloseHandle(FHnd);			
			}
			GlobalUnlock(hDIB);    
			GlobalFree(hDIB);	
		}
		else
			MessageBox(hWnd, "Error", "Message", MB_ICONWARNING);				
		RePaint();
	}	
}
...
#ifndef CS_STATIC_DLL
...
    DRAWCADTOBITMAP CMainWindow::DrawCADtoBitmap;
MainWindow.h:

Code: Select all

class CMainWindow : public CWindow  
{
#ifndef CS_STATIC_DLL 
	static DRAWCADTOBITMAP DrawCADtoBitmap;
It cuts off a half of the loaded image and saves it to a file using DrawCADtoBitmap. Please try it with your files.

Sergey.
Technical Support E-mail: support@cadsofttools.com
Chat support on Skype: cadsofttools.support

Post Reply