几何尺寸与公差论坛------致力于产品几何量公差标准GD&T (GDT:ASME)|New GPS(ISO)研究/CAD设计/CAM加工/CMM测量  


返回   几何尺寸与公差论坛------致力于产品几何量公差标准GD&T (GDT:ASME)|New GPS(ISO)研究/CAD设计/CAM加工/CMM测量 » 仿射空间:CAX软件开发(三)二次开发与程序设计 » CAD二次开发 » AutoCAD二次开发 » DirectDWG
用户名
密码
注册 帮助 会员 日历 银行 搜索 今日新帖 标记论坛为已读


 
 
主题工具 搜索本主题 显示模式
旧 2009-05-04, 06:51 PM   #1
yang686526
高级会员
 
注册日期: 06-11
帖子: 14579
精华: 1
现金: 224494 标准币
资产: 234494 标准币
yang686526 向着好的方向发展
默认 【转帖】cropping issues

cropping issues
cropping issues
this issue comes from a founding member. we have a relatively simple application that renders cad drawings to bitmaps. part of this application allows cropping a region of the drawing and then rendering the cropped region to a bitmap. a user of the application needs to be able to crop contiguous regions of the drawing and then stitch these rendered regions together to reform the original image. however, when we try to crop contiguous regions of the drawing we end up with cropped images that overlap each other and in which the drawn elements are not rendered to the same scale. this prevents the cropped regions from being stitched together.
the attached zip file contains the source image and the rendered bitmaps from attempting this cropping. the source image is hummer.dwg and all bitmaps result from rendering the "color" layout. two test scenarios were performed. in both scenarios, device canvas is first sized to a width of 1000 and height of 800 (this is done with sx->pdevice->onsize, which can be seen in the code below.) the uncropped bitmap is in the file hummer-1000x800.bmp. in the first scenario we create two cropped images, the first starting at xoffset 0 , yoffset 0, with a width of 700 and height of 350, the second starting at xoffset 700, yoffset 0, with a width of 300 and height of 350. when put together, the two output bitmaps should form a contiguous strip of the original image, but they do not. they overlap in the x dimension and the y dimensions do not line up. this output can be seen in the files hummer-c0-0-700-350.bmp and hummer-c700-0-300-350.bmp.
in the second scenario, we crop the image into 4 strips, each strip containing the full width of the image, but at a height of 200 pixels. these strips should be able to be stitched together to form the complete image, but looking at the output bitmap files, one sees a tremendous amount of overlap between the strips.
the code related to this operation is included below. this is code is based on the cropping and zooming code from odamfcapp. in fact one can see similar behavior in odamfcapp when using the zoom window tool. for example, when selecting a wide but short section of an image to zoom with the zoom window, the resulting output contains more of the image than was contained in the selected zoom section.
in the code below, you will see that cropping is performed by calling our function cropviewtorect. this function is also included below.
please let us know if this behavior is a bug in the library or if we are doing something incorrect. if we need to accomplish the desired behavior some other way, please let us know how to do this. this is a critical issue, so we hope to hear from you soon. thanks.
code:
void cadrenderbitmap()
{
try
{
odgepoint3d position;
odgepoint3d target;
odgevector3d upvector;
double fieldwidth = 0;
double fieldheight = 0;
bool redrawrequired = false;
// in order to allow for multiple calls to req_exec for the same input file, the bitmap
// device must be created each time exec is called to render an image.
sx->pdevice = sx->pgs->createbitmapdevice();
opverify(!sx->pdevice.isnull(), s.pp, err_unexpected_error + cad_error_create_device);
// set the bit depth.
sx->pdevice->properties()->putat("bitperpixel", odrxvariantvalue(oduint32(s.pp->u.cad.renderbitdepth)));
// according to the open design alliance, setting this flag improves bitmap output and it should be set.
sx->pcontext->setplotgeneration(1);
// set the color of the area outside of the drawing and background area.
// this is visible if a drawing is rendered to a different aspect ratio than that contained in the layout.
// this area is analogous the black bands seen when viewing a widescreen movie on a non-widescreen tv.
odcolorref backgroundcolor = odrgb(s.pp->u.cad.backgroundcolor.rgbred,
s.pp->u.cad.backgroundcolor.rgbgreen,
s.pp->u.cad.backgroundcolor.rgbblue);
sx->pdevice->setbackgroundcolor(backgroundcolor);
// set the logical palette. this controls the color of the area directly behind the drawing elements.
// the key to making this work is ensuring that array element 0 of the palette copy array ("ppalcpy") is
// set to the desired background color. if this step is omitted, then the area directly behind the drawing elements will
// not be the desired color. this code was copied from the dwg direct bitmap rendering example.
const odcolorref* palette = odcmacadpalette(backgroundcolor);
odgspalette ppalcpy;
const int palettenumcolors = 256;
ppalcpy.insert(ppalcpy.begin(), palette, palette+palettenumcolors);
ppalcpy[0] = backgroundcolor;
sx->pdevice->setlogicalpalette(ppalcpy.asarrayptr(), palettenumcolors);
// set the color of the drawing background area.
sx->pcontext->setpalettebackground(backgroundcolor);
// set layers on or off, as requested by the client.
setlayeronoffstatus(sx->pdb);
if ( ((long)s.pp->u.cad.layouttorender != s.previouslayout) || (outputsizechanged()) )
{
redrawrequired = true;
s.previouslayout = (long)s.pp->u.cad.layouttorender;
if ( (s.pp->flags & f_crop) || (s.pp->flags & f_inputcrop) )
{
s.previouswidth = s.cropwidth;
s.previousheight = s.cropheight;
}
else
{
s.previouswidth = s.pp->u.cad.renderwidth;
s.previousheight = s.pp->u.cad.renderheight;
}
// determine the layout to render, based upon client input, and setup the layout.
oddbobjectid layoutid = getlayouttorender(sx->pdb);
if (isactivelayout(sx->pdb, layoutid))
{
sx->playouthelper = oddbgsmanager::setupactivelayoutviews(sx->pdevice, sx->pcontext);
}
else
{
sx->playouthelper = oddbgsmanager::setuplayoutviews (layoutid, sx->pdevice, sx->pcontext);
}
// open the layout.
oddblayoutptr playoutobj = layoutid.safeopenobject ();
opverify(!playoutobj.isnull(), s.pp, err_unexpected_error + cad_error_create_layout);
}
// set the device to the layout helper. for multiple req_execs, this may be a previously
// created layout helper.
sx->pdevice = sx->playouthelper;

// size the drawing to the size specified by the client.
odgsdcrect canvasrect(0, s.pp->u.cad.renderwidth, 0, s.pp->u.cad.renderheight);
sx->pdevice->onsize(canvasrect);
// redrawing the image is required if a different layout is being rendered, or the output size
// has changed from the previous output size.
if (redrawrequired)
{
// zooming to extents is sometimes required to fill the specified bitmap size with the drawing.
// for a model space layout, if we don't zoom to extents, for some drawings, some of the
// drawing elements are cropped. on the other hand, for some paper space layout drawings,
// for some drawings, zooming to extents causes some of the drawing elements to be cropped.
// therefore, only zoom to extents for the model space layout.
cad_layout *pcadlayouts = s.pp->u.cad.layouts;
if (strncmp(pcadlayouts[s.pp->u.cad.layouttorender].name, modellayoutname, modelnamelength) == 0)
{
odabstractviewpeptr(sx->playouthelper->activeview())->zoomextents(sx->playouthelper->activeview());
}
}
// save the current view attributes so they can be restored later.
position = sx->playouthelper->activeview()->position();
target = sx->playouthelper->activeview()->target();
upvector = sx->playouthelper->activeview()->upvector();
fieldwidth = sx->playouthelper->activeview()->fieldwidth();
fieldheight = sx->playouthelper->activeview()->fieldheight();
// some 3d images, when initially displayed, are tilted on the z-axis. in this case, when they are rendered
// again for a subsequent req_exec, the amount of tilt on the z-axis may change. in order to prevent this,
// setview is called here. this ensures that all 3d images are always displayed on a flat plane, with regards
// to the z-axis. some other cad viewers always display 3d images on a flat plane, others display the image
// tilted (if the current state of the image is tiled in the file). this means that our rendering may differ
// from those viewers which display the images tilted. however, at this point, this seems to be the only way
// to work around the issue of the image perspective changing on multiple execs.
sx->playouthelper->activeview()->setview(position,target,upvector,fieldwidth,fieldheight);
// if requested, crop the image.
if ( (s.pp->flags & f_crop) || (s.pp->flags & f_inputcrop) )
{
cropviewtorect(sx->playouthelper->activeview(), canvasrect, odgsdcrect(s.cropxoff, s.cropxoff + s.cropwidth,
s.cropyoff, s.cropyoff + s.cropheight));
// resize the drawing to the cropped size.
sx->pdevice->onsize(odgsdcrect(0, s.cropwidth, 0, s.cropheight));
}
// generate the bitmap and place it in the put queue.
sx->pdevice->update();
generatebitmap(odgirasterimageptr(sx->pdevice->properties()->getat("rasterimage")));
// in order to support multiple req_execs, the image must now be "uncropped" back to
// its original state. if we don't do this, a subsequent req_exec will be operating
// on the cropped image and the user will not get the expected results.
if ( (s.pp->flags & f_crop) || (s.pp->flags & f_inputcrop) )
{
// to "uncrop" the image, restore the previously saved view attributes.
sx->playouthelper->activeview()->setview(position,target,upvector,fieldwidth,fieldheight);
}
}
catch (oderror& e)
{
#ifdef _debug
// capture the error description text to assist in debugging.
odstring s = e.description();
#endif
// force opverify to report an error and report the error code raised by the library
opverify(0, s.pp, err_unexpected_error - e.code());
}
catch (...)
{
// force opverify to report an error.
opverify(0, s.pp, err_unexpected_error);
}
// dwgdirect is not terminated here, so that multiple req_execs can be executed. the device is recreated
// for each req_exec, so release it here.
if (!(sx->pdevice.isnull()))
{
sx->pdevice.release();
}
}
void cropviewtorect (odgsview* pview, odgsdcrect canvasrect, odgsdcrect croprect)
{
// determine the center of the current canvas and the requested crop rectangle
odgsdcpoint canvascenter((canvasrect.m_max.x + canvasrect.m_min.x) / 2, (canvasrect.m_max.y + canvasrect.m_min.y) / 2);
odgsdcpoint cropcenter((croprect.m_max.x + croprect.m_min.x) / 2, (croprect.m_max.y + croprect.m_min.y) / 2);
// dolly the view to the cropped center point.
odgevector3d vec(-(canvascenter.x - cropcenter.x), -(canvascenter.y - cropcenter.y), 0.0);
vec.transformby((pview->screenmatrix() * pview->projectionmatrix()).inverse());
pview->dolly(vec);
double widthfactor = double(canvasrect.m_max.x - canvasrect.m_min.x) / double(croprect.m_max.x - croprect.m_min.x);
double heightfactor = double(canvasrect.m_max.y - canvasrect.m_min.y) / double(croprect.m_max.y - croprect.m_min.y);
// zoom to fill the cropped rectangle.
pview->zoom(__min(widthfactor, heightfactor));
}
void generatebitmap(const odgirasterimage* praster)
{
// retrieve bitmapinfoheader information.
s.pp->head.bisize = sizeof(bitmapinfoheader);
s.pp->head.biwidth = praster->pixelwidth();
s.pp->head.biheight = praster->pixelheight();
s.pp->head.biplanes = 1;
s.pp->head.bibitcount = (word)praster->colordepth();
s.pp->head.bicompression = bi_rgb;
s.pp->head.bisizeimage = 0;
s.pp->head.bixpelspermeter = 0;
s.pp->head.biypelspermeter = 0;
s.pp->head.biclrused = praster->numcolors();
s.pp->head.biclrimportant = 0;
// retrieve the color palette.
praster->palettedata((oduint8 *)s.pp->colortable);
// retrieve the scan lines.
// note that the library always renders bitmaps and returns scanlines that are padded to
// 4-byte boundaries. there is no way to instruct the library to render different sized scanlines.
// however, the client may have requested no padding or a different amount of
// padding. this desired output line size is specified in the pic parms widthpad field.
oduint32 scanlinesize(praster->scanlinesize());
byte* pline;
pline = (byte *)opcalloc(1, scanlinesize);
// the bitmap is already in bottom up order, so we need to start with the last scan line.
for(long i = s.pp->head.biheight - 1; i >=0; i--)
{
// retrieve a single scan line, at position 'i'.
praster->scanlines(pline, i, 1);
pwritecrop(pline, s.pp->u.cad.widthpad, 0, min(s.pp->u.cad.widthpad, scanlinesize));

}
opfree(pline);
you need set active view width and height to have the same aspect ratio (width/height) as device rectangle has.
widthfactor and height factor should be equal.
else scale is adjusted to get all active view area visible in device rectangle.
sergey slezkin
prior to your reply, i was playing with this. you have seen in the last line of the function cropviewtorect that i was zooming to the __min of widthfactor and heightfactor. i changed this to zoom to the __max of widthfactor and heightfactor and everything now seems to be working as expected.
does it make sense to you that this change would result in crop regions that can be correctly stitched together?
as i asked in my previous post, i would like to know why zooming to the max zoom factor seems to work and if there are any potential problems in doing this. thank you.
hi,
mfcapp has preview functionality. preview has two modes - via geometry and via bitmap. geometry mode - it just rendering of layout to preview window. bitmap mode - render layout to bitmap at first and draw bitmap to preview window next. by default it uses geometry mode. you can change mode in option menu. bitmap mode was added to support 3d rendering. next moment of bitmap mode is working via small bitmap squares. it render piece of layout to small bitmap - render it, step to next piece... and so on. so it can be helpful for your task.
regarding to your code... in my understanding you should make two steps - define layout square - what you want to view and define device square - place to plot. so if you have layout extents x-100 100 y-100 100 and want to get two bitmaps with left and right part of layout, you should create two bitmaps of size 100,200. and make two calls
setview((-50,0,-1),(-50,0,0),yaxis,100,200
onsize(odgsdcrect(0, 100, 0, 200))
update
setview(( 50,0,-1),( 50,0,0),yaxis,100,200
onsize(odgsdcrect(0, 100, 0, 200))
update
yang686526离线中   回复时引用此帖
GDT自动化论坛(仅游客可见)
 


主题工具 搜索本主题
搜索本主题:

高级搜索
显示模式

发帖规则
不可以发表新主题
不可以回复主题
不可以上传附件
不可以编辑您的帖子

vB 代码开启
[IMG]代码开启
HTML代码关闭

相似的主题
主题 主题发起者 论坛 回复 最后发表
【转帖】attribute issues yang686526 DirectDWG 0 2009-05-04 04:22 PM
【转帖】are these issues regreessions in dd1.14.02 for net2003 yang686526 DirectDWG 0 2009-05-04 04:10 PM
【转帖】sw 2009 issues yang686526 SolidWorks二次开发 0 2009-04-13 02:44 PM
【转帖】bill of material issues in solidworks yang686526 SolidWorks二次开发 0 2009-04-13 09:16 AM


所有的时间均为北京时间。 现在的时间是 09:00 AM.


于2004年创办,几何尺寸与公差论坛"致力于产品几何量公差标准GD&T | GPS研究/CAD设计/CAM加工/CMM测量"。免责声明:论坛严禁发布色情反动言论及有关违反国家法律法规内容!情节严重者提供其IP,并配合相关部门进行严厉查处,若內容有涉及侵权,请立即联系我们QQ:44671734。注:此论坛须管理员验证方可发帖。
沪ICP备06057009号-2
更多