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 >
C/C++ Source or Header  |  1997-02-11  |  7KB  |  223 lines

  1. /*
  2. Sample Vdraft C++ code - Vleader.cpp
  3.     (C) Copyright 1997 by SoftSource.  All rights reserved.
  4. Scott Sherman 2-97
  5.  
  6.     This code demonstrates how to...
  7.         1) add an item to Vdraft's pulldown menu and respond when it's chosen
  8.         2) have the user draw objects and respond when they're done or pick a point
  9.         3) group several commands into one object that appears on the undo list
  10.         4) create a string from a point using the drawing's current unit settings
  11.         5) create and insert a block
  12.     It allows the user to draw a curved leader.
  13. */
  14.  
  15. #include "stdafx.h"
  16. #include "Vdraft.h"
  17. #include <math.h>
  18.  
  19. static IVdraft vdraft;
  20.  
  21. // this block is used as the arrow head
  22. // it gets created if it doesn't already exist in the drawing
  23. // the user can redefine the block if they want a different arrow
  24. CString sArrowBlock("VP_ARROWHEAD");
  25.  
  26. // if we add menu items, we can list them here
  27. enum eMenuItems
  28. {
  29.     eMI_CurvedLeader,
  30. };
  31.  
  32.  
  33.  
  34. // have the user draw an arc
  35. // remember their last pick and use it for the head of the arrow
  36. class cArcEvent : public cDrawEvent
  37. {
  38. public:
  39.     cArcEvent(IVdraft& vdraft, vtAddOnID id, double height) : cDrawEvent(vdraft,id)
  40.     {
  41.         m_point[0] = m_point[1] = m_point[2] = 0;
  42.         m_height = height;
  43.     }
  44.  
  45.     virtual void Done()
  46.     {
  47.         IDocument doc(vdraft.GetActiveDocument());
  48.         IEntities entities(doc.GetEntities());
  49.  
  50.         // get the arc they just drew - it will be the last entity
  51.         IArc arc(entities.GetLast());
  52.         if (arc.GetLength() < m_height)
  53.             return;    // arc is shorter than the arrow - don't draw the arrow
  54.         // use arc to figure out the angle the arrow head should be at
  55.         double angle = calcAngle(arc);
  56.  
  57.         // figure out where the arrow head goes
  58.         IVector head(VECTOR3D(vdraft,m_point[0],m_point[1],m_point[2]));
  59.         IVector scale(VECTOR3D(vdraft,m_height,m_height,m_height));
  60.         IVector normal(arc.GetNormal());
  61.  
  62.         // we want everything we do to make the arrow head grouped under 1 command in the Undo list
  63.         CString description("arrow (");
  64.         IUnits units(doc.GetUnits());
  65.         // get the arrow head point as a string using the current drawing's units
  66.         CString where(units.PointToString(head));    // e.g. 5' 1/2", 2' 3/4"
  67.         description += where;
  68.         description += ")";
  69.         // when the ICommands object goes out of scope, all the commands we've executed
  70.         //        will be bundled under the 'arrow' command & placed on the undo list
  71.         ICommands commands(doc.GetCommands());
  72.         commands.Group(description);
  73.  
  74.         // chop off the part of the arc under the arrow in case it would stick out
  75.         chopArc(arc,angle);
  76.  
  77.         // make sure arrow block exists - create it if not
  78.         arrowBlock(doc);
  79.  
  80.         // insert the arrow head there
  81.         IInsert insert(entities.AddInsert(sArrowBlock));
  82.         insert.SetNormal(normal);
  83.         insert.SetWhere(head);
  84.         insert.SetScaling(scale);
  85.         insert.SetRotation(angle);
  86.     }
  87.  
  88.     // use the user's last point pick for the start of the arrow head
  89.     virtual void Pick(double* point, short picknumber)
  90.     {
  91.         if (picknumber == 3)
  92.         {
  93.             m_point[0] = point[0];
  94.             m_point[1] = point[1];
  95.             m_point[2] = point[2];
  96.         }
  97.     }
  98. protected:
  99.     // how should arrow head be rotated?
  100.     double calcAngle(IArc &arc)
  101.     {
  102.         IVector center(arc.GetWhere()),
  103.             end1(arc.GetWhere1()),    // the endpoints of the arc
  104.             end2(arc.GetWhere2()),
  105.             pick(VECTOR3D(vdraft,m_point[0],m_point[1],m_point[2]));
  106.         double radius = arc.GetRadius();
  107.  
  108.             // angle made by midpoint of arrow's back side, arrow head, center
  109.         double angle1 = acos( m_height / (2*radius) ),
  110.             // angle made by x axis, center, arrow head
  111.             angle2 = atan2(m_point[1] - center.GetY(), m_point[0] - center.GetX() );
  112.  
  113.         // now find out which direction the arc was drawn
  114.         if (pick.Distance(end1) > pick.Distance(end2))
  115.             return PI + angle2 + angle1;
  116.         return PI + angle2 - angle1;
  117.     }
  118.  
  119.     // chop off the part of the arc under the arrow
  120.     // in some cases the arc would otherwise stick out the side of the arrow
  121.     void chopArc(IArc &arc, double angle)
  122.     {
  123.         IVector pick(VECTOR3D(vdraft,m_point[0],m_point[1],m_point[2])),
  124.             // the midpoint of the arrow's backside
  125.             backside(VECTOR3D(vdraft,
  126.                 m_point[0] + m_height * cos(angle),
  127.                 m_point[1] + m_height * sin(angle),
  128.                 m_point[2]));
  129.         arc.Break(pick,backside);
  130.     }
  131.  
  132.     // make sure arrow block exists - create it if not
  133.     void arrowBlock(IDocument &doc)
  134.     {
  135.         IBlocks blocks(doc.GetBlocks());
  136.         if (blocks.GetHasItem(cVariant(sArrowBlock)))
  137.             return;    // the arrow block already exists
  138.  
  139.         // coordinates for arrow head
  140.         IVector origin(VECTOR2D(vdraft,0,0));
  141.         IVector corner1(VECTOR2D(vdraft,1,.1666667));
  142.         IVector corner2(VECTOR2D(vdraft,1,-.1666667));
  143.         // make arrow head entity
  144.         IEntities entities(doc.GetEntities());
  145.         ISolid solid(entities.AddSolid());
  146.         solid.SetWhere(1,origin);
  147.         solid.SetWhere(2,corner1);
  148.         solid.SetWhere(3,corner2);
  149.         solid.SetWhere(4,origin);
  150.  
  151.         // deselect everything & select our new arrow head
  152.         ISelection selection(doc.GetSelection());
  153.         selection.RemoveAll();
  154.         selection.Add(solid);
  155.         // turn selection set into a block so we can use it
  156.         // note: even though we don't use the block that's returned from Add,
  157.         //        we need to make sure it is released - passing it to IBlock does this
  158.         IBlock(blocks.Add(sArrowBlock,origin,cVariant(veBDM_EntitiesRemoved)));
  159.     }
  160.  
  161.     double m_point[3];    // the 1st point of the arc is where the arrow head starts
  162.     double m_height;        // text height is used for arrow head size
  163. };
  164.  
  165. // have the user draw text - when they're done, start them drawing an arc
  166. class cTextEvent : public cDrawEvent
  167. {
  168. public:
  169.     cTextEvent(IVdraft& vdraft, vtAddOnID id) : cDrawEvent(vdraft,id)
  170.     {}
  171.  
  172.     virtual void Done()
  173.     {
  174.         IDocument doc(vdraft.GetActiveDocument());
  175.         IEntities entities(doc.GetEntities());
  176.  
  177.         // get the text they just typed - it will be the last entity
  178.         IText text(entities.GetLast());
  179.         // remember the text height & use it for the arrow head
  180.         double height = text.GetHeight();
  181.  
  182.         // start them drawing a 3 point arc & request notification when they're done
  183.         entities.Draw3PointArc();
  184.         IPickEvents pick(doc.GetPickEvents());
  185.         pick.RequestDraw(getAddOnID(),cVariant(new cArcEvent(vdraft,getAddOnID(),height)));
  186.     }
  187. };
  188.  
  189.  
  190. // the user has selected to draw a curved leader
  191. // start them drawing an arc & request to be notified of draw events
  192. veReturn vfCommand(vtAddOnID id, long eventid)
  193. {
  194.     if (eventid != eMI_CurvedLeader)
  195.         return veR_OK;
  196.     IDocument doc(vdraft.GetActiveDocument());
  197.  
  198.     // have them draw text
  199.     IEntities entities(doc.GetEntities());
  200.     entities.DrawText();
  201.  
  202.     // ask to be notified when they're done
  203.     IPickEvents pick(doc.GetPickEvents());
  204.     pick.RequestDraw(id,cVariant(new cTextEvent(vdraft,id)));
  205.  
  206.     return veR_OK;
  207. }
  208.  
  209. // add a menu item to Vdraft
  210. veReturn vfLoad(vtAddOnID id)
  211. {
  212.     if (!vdraft.CreateDispatch("Vdraft.Application", NULL))
  213.         return veR_Unload;
  214.     CString item("&Curved Leader"),
  215.         status("Draw an arc with an arrow and text");
  216.     IApplicationEvents events(vdraft.GetEvents());
  217.     events.AddToolsCommand(id,eMI_CurvedLeader,item,status);
  218.  
  219.     CString keys("cleader");
  220.     events.AddKeyboardCommand(id,eMI_CurvedLeader,keys);
  221.     return veR_OK;
  222. }
  223.