home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 November
/
pcwk_11_98a.iso
/
Wtestowe
/
SOFTSRC
/
vtrial15.exe
/
DATA.1
/
Vleader.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1997-02-11
|
7KB
|
223 lines
/*
Sample Vdraft C++ code - Vleader.cpp
(C) Copyright 1997 by SoftSource. All rights reserved.
Scott Sherman 2-97
This code demonstrates how to...
1) add an item to Vdraft's pulldown menu and respond when it's chosen
2) have the user draw objects and respond when they're done or pick a point
3) group several commands into one object that appears on the undo list
4) create a string from a point using the drawing's current unit settings
5) create and insert a block
It allows the user to draw a curved leader.
*/
#include "stdafx.h"
#include "Vdraft.h"
#include <math.h>
static IVdraft vdraft;
// this block is used as the arrow head
// it gets created if it doesn't already exist in the drawing
// the user can redefine the block if they want a different arrow
CString sArrowBlock("VP_ARROWHEAD");
// if we add menu items, we can list them here
enum eMenuItems
{
eMI_CurvedLeader,
};
// have the user draw an arc
// remember their last pick and use it for the head of the arrow
class cArcEvent : public cDrawEvent
{
public:
cArcEvent(IVdraft& vdraft, vtAddOnID id, double height) : cDrawEvent(vdraft,id)
{
m_point[0] = m_point[1] = m_point[2] = 0;
m_height = height;
}
virtual void Done()
{
IDocument doc(vdraft.GetActiveDocument());
IEntities entities(doc.GetEntities());
// get the arc they just drew - it will be the last entity
IArc arc(entities.GetLast());
if (arc.GetLength() < m_height)
return; // arc is shorter than the arrow - don't draw the arrow
// use arc to figure out the angle the arrow head should be at
double angle = calcAngle(arc);
// figure out where the arrow head goes
IVector head(VECTOR3D(vdraft,m_point[0],m_point[1],m_point[2]));
IVector scale(VECTOR3D(vdraft,m_height,m_height,m_height));
IVector normal(arc.GetNormal());
// we want everything we do to make the arrow head grouped under 1 command in the Undo list
CString description("arrow (");
IUnits units(doc.GetUnits());
// get the arrow head point as a string using the current drawing's units
CString where(units.PointToString(head)); // e.g. 5' 1/2", 2' 3/4"
description += where;
description += ")";
// when the ICommands object goes out of scope, all the commands we've executed
// will be bundled under the 'arrow' command & placed on the undo list
ICommands commands(doc.GetCommands());
commands.Group(description);
// chop off the part of the arc under the arrow in case it would stick out
chopArc(arc,angle);
// make sure arrow block exists - create it if not
arrowBlock(doc);
// insert the arrow head there
IInsert insert(entities.AddInsert(sArrowBlock));
insert.SetNormal(normal);
insert.SetWhere(head);
insert.SetScaling(scale);
insert.SetRotation(angle);
}
// use the user's last point pick for the start of the arrow head
virtual void Pick(double* point, short picknumber)
{
if (picknumber == 3)
{
m_point[0] = point[0];
m_point[1] = point[1];
m_point[2] = point[2];
}
}
protected:
// how should arrow head be rotated?
double calcAngle(IArc &arc)
{
IVector center(arc.GetWhere()),
end1(arc.GetWhere1()), // the endpoints of the arc
end2(arc.GetWhere2()),
pick(VECTOR3D(vdraft,m_point[0],m_point[1],m_point[2]));
double radius = arc.GetRadius();
// angle made by midpoint of arrow's back side, arrow head, center
double angle1 = acos( m_height / (2*radius) ),
// angle made by x axis, center, arrow head
angle2 = atan2(m_point[1] - center.GetY(), m_point[0] - center.GetX() );
// now find out which direction the arc was drawn
if (pick.Distance(end1) > pick.Distance(end2))
return PI + angle2 + angle1;
return PI + angle2 - angle1;
}
// chop off the part of the arc under the arrow
// in some cases the arc would otherwise stick out the side of the arrow
void chopArc(IArc &arc, double angle)
{
IVector pick(VECTOR3D(vdraft,m_point[0],m_point[1],m_point[2])),
// the midpoint of the arrow's backside
backside(VECTOR3D(vdraft,
m_point[0] + m_height * cos(angle),
m_point[1] + m_height * sin(angle),
m_point[2]));
arc.Break(pick,backside);
}
// make sure arrow block exists - create it if not
void arrowBlock(IDocument &doc)
{
IBlocks blocks(doc.GetBlocks());
if (blocks.GetHasItem(cVariant(sArrowBlock)))
return; // the arrow block already exists
// coordinates for arrow head
IVector origin(VECTOR2D(vdraft,0,0));
IVector corner1(VECTOR2D(vdraft,1,.1666667));
IVector corner2(VECTOR2D(vdraft,1,-.1666667));
// make arrow head entity
IEntities entities(doc.GetEntities());
ISolid solid(entities.AddSolid());
solid.SetWhere(1,origin);
solid.SetWhere(2,corner1);
solid.SetWhere(3,corner2);
solid.SetWhere(4,origin);
// deselect everything & select our new arrow head
ISelection selection(doc.GetSelection());
selection.RemoveAll();
selection.Add(solid);
// turn selection set into a block so we can use it
// note: even though we don't use the block that's returned from Add,
// we need to make sure it is released - passing it to IBlock does this
IBlock(blocks.Add(sArrowBlock,origin,cVariant(veBDM_EntitiesRemoved)));
}
double m_point[3]; // the 1st point of the arc is where the arrow head starts
double m_height; // text height is used for arrow head size
};
// have the user draw text - when they're done, start them drawing an arc
class cTextEvent : public cDrawEvent
{
public:
cTextEvent(IVdraft& vdraft, vtAddOnID id) : cDrawEvent(vdraft,id)
{}
virtual void Done()
{
IDocument doc(vdraft.GetActiveDocument());
IEntities entities(doc.GetEntities());
// get the text they just typed - it will be the last entity
IText text(entities.GetLast());
// remember the text height & use it for the arrow head
double height = text.GetHeight();
// start them drawing a 3 point arc & request notification when they're done
entities.Draw3PointArc();
IPickEvents pick(doc.GetPickEvents());
pick.RequestDraw(getAddOnID(),cVariant(new cArcEvent(vdraft,getAddOnID(),height)));
}
};
// the user has selected to draw a curved leader
// start them drawing an arc & request to be notified of draw events
veReturn vfCommand(vtAddOnID id, long eventid)
{
if (eventid != eMI_CurvedLeader)
return veR_OK;
IDocument doc(vdraft.GetActiveDocument());
// have them draw text
IEntities entities(doc.GetEntities());
entities.DrawText();
// ask to be notified when they're done
IPickEvents pick(doc.GetPickEvents());
pick.RequestDraw(id,cVariant(new cTextEvent(vdraft,id)));
return veR_OK;
}
// add a menu item to Vdraft
veReturn vfLoad(vtAddOnID id)
{
if (!vdraft.CreateDispatch("Vdraft.Application", NULL))
return veR_Unload;
CString item("&Curved Leader"),
status("Draw an arc with an arrow and text");
IApplicationEvents events(vdraft.GetEvents());
events.AddToolsCommand(id,eMI_CurvedLeader,item,status);
CString keys("cleader");
events.AddKeyboardCommand(id,eMI_CurvedLeader,keys);
return veR_OK;
}