下面的示例绘制一个以原点为中心的单位圆。绘制的确切圆取决于视口对圆的视图。目标是用具有最少可识别段数的折线绘制一个圆。使用 VPORTS 命令,您可以创建四个视口,然后单击一个并放大圆圈,然后单击另一个并从中备份。执行 REGENALL 时,每个视口都会计算其自己的最小分段的圆折线表示。 这就是该示例计算折线中必要线段数的方式。首先,给定一个以原点为中心且位于XY平面中的给定半径的圆,并给定一条以半径 - 0.5 像素与 X 轴相交的垂直线,确定X轴与从原点延伸到垂直线与圆相交的点的线段之间的角度。两个 pi 除以此角度提供了折线看起来像圆所需的最小段数。用户将无法区分构成圆的各个线段,因为视觉差异小于一个像素。 ![]() Adesk::Boolean
AsdkTesselateSamp::subWorldDraw(AcGiWorldDraw *pW)
{
// Draw a red 1 x 1 drawing-unit square centered at the
// world coordinate origin and parallel to the XY-plane.
//
const Adesk::UInt32 num_pts = 5;
AcGePoint3d verts[num_pts];
verts[0] = verts[4] = AcGePoint3d(-0.5, -0.5, 0.0);
verts[1] = AcGePoint3d( 0.5, -0.5, 0.0);
verts[2] = AcGePoint3d( 0.5, 0.5, 0.0);
verts[3] = AcGePoint3d(-0.5, 0.5, 0.0);
pW- >subEntityTraits().setColor(kRed);
pW->geometry ().polyline(num_pts, verts);
// If regenType is kAcGiSaveWorldDrawForProxy then we
// must return Adesk::kTrue, otherwise we need to return
// Adesk::kFalse to trigger calls to our viewportDraw().
//
return (pW- >regenType() == kAcGiSaveWorldDrawForProxy);
}
void
AsdkTesselateSamp::subViewportDraw(AcGiViewportDraw *pV)
{
static double two_pi = atan(1.0) * 8.0;
// Get the number of pixels on the X- and Y-edges of
// a unit square centered at (0.0, 0.0, 0.0), in
// world coordinates.
//
AcGePoint3d center(0.0, 0.0, 0.0);
AcGePoint2d area;
pV->viewport ().getNumPixelsInUnitSquare(center, area);
// If the 'area' values are negative, then we are in
// perspective mode and the 'center' is too close or
// in back of the viewport.
//
if (area.x > 0.0) {
// Print out the number of pixels along the
// y-axis of the unit square used in
// getNumPixelsInUnitSquare.
//
AcGeVector3d norm(0.0, 0.0, 1.0);
AcGeVector3d dir(1.0, 0.0, 0.0);
TCHAR buf[100];
_stprintf(buf, _T("%7.3lf"), area.y);
pV->geometry ().text(center, norm, dir, 1.0, 1.0,
0.0, buf);
// Draw a circle that depends on how big the circle
// is in the viewport. This is a problem of
// figuring out the least number of segments needed
// by a polyline so it doesn't look segmented.
//
// By the way, the worldDraw() and viewportDraw() of
// an entity in a viewport are only called during a
// regen and not necessarily during a ZOOM or PAN.
// The reason is that a REGEN produces something
// akin to a very high resolution image internally
// that AutoCAD can zoom in or pan around,
// until you get too close to this image or any of
// its edges -- at which point a REGEN is internally
// invoked for that viewport and a new internal
// image is created (ready to be mildly zoomed and
// panned upon.)
//
double radius = 0.5;
double half_pixel_hgt = 2.0 / area.x; // in world
// coords
int num_segs = 8;
double angle = two_pi / num_segs;
if (half_pixel_hgt > radius / 2) {
// The circle is around or less than the size
// of a pixel. So generate a very small octagon.
num_segs = 8;
} else {
// Given a circle centered at the origin of a
// given 'radius' in the XY-plane, and given a
// vertical line that intersects the X-axis at
// 'radius - half a pixel', what is the angle
// from the X- axis of a line segment from the
// origin to the point where the vertical line
// and the circle intersect? Two pi divided by
// this angle gives you a minimum number of
// segments needed by a polyline to 'look' like
// a circle and not be able to differentiate
// the individual segments because the visual
// differences are less than the size of a
// pixel. (This is not the only way to figure
// this out but it's sufficient.)
//
angle = acos ((radius - 1.0 / (area.x / 2.0))
/ radius);
double d_num_segs = two_pi / angle;
// Limit the number of segments from 8 to
// 128 and use whole numbers for
// this count.
//
if (d_num_segs < 8.0) {
num_segs = 8;
} else if (d_num_segs > 128.0) {
num_segs = 128;
} else {
num_segs = (int)d_num_segs;
}
}
// Calculate the vertices of the polyline from the
// start, around the circle, and back to the start
// to close the polyline.
//
angle = 0.0;
double angle_inc = two_pi / (double)num_segs;
AcGePoint3d* verts = new AcGePoint3d[num_segs + 1];
for (int i = 0; i <= num_segs; i++,
angle += angle_inc)
{
verts[i].x = center.x + radius * cos(angle);
verts[i].y = center.y + radius * sin(angle);
verts[i].z = center.z;
}
pV->geometry ().polyline(num_segs + 1, verts);
delete [] verts;
}
}
|
|Archiver|CAD开发者社区
( 苏ICP备2022047690号-1 苏公网安备32011402011833)
GMT+8, 2025-10-29 06:58
Powered by Discuz! X3.4
Copyright © 2001-2021, Tencent Cloud.