Thanks guys. I appreciate it.
But I've been working on this for ever now.
Since Glenn helped me with a circle jig I thought I'ld bang out the poly jig.
I keep getting so close (Oh yeah, I'll have this sewn up in a jiffy) and then whatever I fixed something worse comes along. I did see Kean's post pretty early but didn't take it in too much as I wanted to do it on my own.
There's a couple of things he did that looked a bit funny so I took another tack (I didn't want to make a dummy polyline) however the way jigs differ from other code I think he took the sensible rout.
This works pretty good on the 2d and works for a bit on the 3d then throws a wobbler.
using System;
using System.Windows.Forms;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace Plinejigging
{
public class PlineJiggy
{
public class PolyArcJiggy
{
public class PolyArcJig : EntityJig
{
private Point2d startP, endP, FirstPt, midPt;
private Vector3d _normal;
private double sAng, eAng;
private Plane pn;
private Point3d BasePt, SecondPt, endP3d, Cen3d;
private Util.MyMath.Slope S2;
private int i, Vcnt;
private PromptPointResult dres;
private bool bSecondPt = false;
private double El;
public PolyArcJig(Vector3d Normalvec, int iVertex,
Point3d BaseP, Vector3d Firstderiv,
Plane oPlane,double Elev, bool bSecond)
: base(new Arc())
{
Vcnt = iVertex;
pn = oPlane;
BasePt = BaseP; //Still need a point in ucs for prompts
startP = BasePt.Convert2d(pn);
Vector3d V = Firstderiv;
SecondPt = new Point3d(V.X, V.Y, V.Z);//only for the second pt option
FirstPt=startP.Subtract(V.Convert2d(pn));
_normal = Normalvec;
bSecondPt = bSecond;
El = Elev;
if (bSecondPt)
{
Vector2d Vmid = Firstderiv.Convert2d(pn);
midPt = new Point2d(Vmid.X, Vmid.Y);
}
else
{
S2 = Util.MyMath.EndSlope(FirstPt, startP);
}
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
JigPromptPointOptions jigOpts = new JigPromptPointOptions();
jigOpts.UserInputControls = (UserInputControls.Accept3dCoordinates) |
UserInputControls.NullResponseAccepted;
if (Vcnt > 1)
{
jigOpts.SetMessageAndKeywords(
"\nSpecify next point or [Angle/Close/Line/Second pt/Undo]:",
"Angle Close Line Second Undo");
}
else
{
jigOpts.SetMessageAndKeywords(
"\nSpecify next point or [Angle/Line/Second pt/Undo]:",
"Angle Line Second Undo");
}
jigOpts.BasePoint = BasePt;
if (bSecondPt)
{
jigOpts.Message = "\nSpecify end point of arc:";
jigOpts.BasePoint = SecondPt;
}
jigOpts.UseBasePoint = true;
dres = prompts.AcquirePoint(jigOpts);
if (dres.Status == PromptStatus.None)
{
return SamplerStatus.Cancel;
}
switch (dres.StringResult)
{
case "Angle":
//Todo
break;
case "Line":
return SamplerStatus.OK;
}
Point2d endPointTemp = dres.Value.Convert2d(pn);
if (endPointTemp != endP)
{
endP = endPointTemp;
if (bSecondPt)
{
endP3d = dres.Value;
}
}
else
return SamplerStatus.NoChange;
if (dres.Status == PromptStatus.Cancel)
return SamplerStatus.Cancel;
else
return SamplerStatus.OK;
}//End sampler
protected override bool Update()
{
try
{
Point2d Cen;
if (bSecondPt)
{
Cen3d = Util.MyMath.CenterFrom3Pts(BasePt, endP3d, SecondPt);
Cen = Cen3d.Convert2d(pn);
i = Util.MyMath.isLeft(startP, endP, midPt);
}
else
{
Util.MyMath.Slope S1 = Util.MyMath.Bisector(startP, endP);
Cen = Util.MyMath.PointFromSlopes(S1, S2);
Cen3d = new Point3d(pn, Cen);
Cen3d= Cen3d.Add(_normal.MultiplyBy(El));
//Cen3d = new Point3d( Cen.X,Cen.Y,0);
i = Util.MyMath.isLeft(FirstPt, endP, startP);
}
double Rad = Cen.GetDistanceTo(startP);
if (i == 1)
{
sAng = Util.MyMath.AngFromX(Cen, endP);
eAng = Util.MyMath.AngFromX(Cen, startP);
}
else if (i == -1)
{
sAng = Util.MyMath.AngFromX(Cen, startP);
eAng = Util.MyMath.AngFromX(Cen, endP);
}
else
{
sAng = Util.MyMath.AngFromX(Cen, startP);
eAng = Util.MyMath.AngFromX(Cen, endP);
i = -1;
}
((Arc)Entity).StartAngle = sAng;
((Arc)Entity).EndAngle = eAng;
((Arc)Entity).Center = Cen3d;
((Arc)Entity).Radius = Rad;
((Arc)Entity).Normal = _normal;
}
catch (System.Exception)
{
return false;
}
return true;
}//End Update
public PromptPointResult Res()
{
return dres;
}
public int MinusPlus()
{
return -i;
}
public Entity GetEntity()
{
return Entity;
}
}// class PolyArcJig
#region Command Declarations
[CommandMethod("DrawPline")]
public void PlineDraw()
{
int iVertex = 0;
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
bool makepline = true, bCurve = false;
Polyline oPline = new Polyline(3);
oPline.SetDatabaseDefaults();
PromptPointResult Res2 = null;
ObjectId id = ObjectId.Null;
double Bulge = 0;
PolyArcJig jig ;
Transaction tr=null;
Matrix3d ucs = ed.CurrentUserCoordinateSystem;
Vector3d Norm = new Vector3d(0, 0, 1).TransformBy(ucs);
Plane pn = new Plane(new Point3d(0, 0, 0), Norm);
Plane pn2 = new Plane(ucs.CoordinateSystem3d.Origin, Norm);
double Elev=-pn2.Coefficients.D;
oPline.Elevation = Elev;
oPline.Normal = Norm;
PromptPointResult Res1 = ed.GetPoint("\nSpecify start point:");
if (Res1.Status != PromptStatus.OK) return;
Point3d BasePt = Res1.Value;
//Base point needs to stay in ucs
Point2d P = Res1.Value.TransformBy(ucs).Convert2d(pn);
oPline.AddVertexAt(0, P, 0, 0, 0);
PromptPointOptions PPO = new PromptPointOptions("\nSpecify next point or [Arc]:", "Arc");
PPO.UseBasePoint = true;
PPO.UseDashedLine = true;
PPO.AllowNone = true;
while (Res1.Status == PromptStatus.OK || Res1.Status == PromptStatus.Keyword)
{
try //add verticies
{
using (tr = db.TransactionManager.StartTransaction())
{
PPO.BasePoint = BasePt;
if (bCurve) goto Skip; //we already have a picked point
if (iVertex > 1)
{
PPO.SetMessageAndKeywords(
"\nSpecify next point or [Arc/Close/Undo]:", "Arc Close Undo");
}
LineSkip:
Res2 = ed.GetPoint(PPO);
Skip:
if (Res2.Status == PromptStatus.Cancel) return;
if (Res2.Status == PromptStatus.None) return;
if (Res2.StringResult == "Arc" || bCurve)
{
if (iVertex == 0)
{
double lastAngle = (double)acadApp.GetSystemVariable("LASTANGLE");
Vector3d V = new Vector3d(1, Math.Tan(lastAngle), 0);
Point3d D = Res1.Value.TransformBy(ucs).Subtract(V);
jig = new PolyArcJig(Norm, iVertex, Res1.Value.TransformBy(ucs),
D.GetAsVector(), pn, Elev, false);
}
else
{
jig = new PolyArcJig(Norm, iVertex,
oPline.GetPoint3dAt(iVertex),
oPline.GetFirstDerivative(iVertex), pn, Elev, false);
}
if (ed.Drag(jig).Status == PromptStatus.Cancel)
return;
else
Res2 = jig.Res();
if (Res2.Status == PromptStatus.None) return;
if (Res2.Status == PromptStatus.Keyword)
{
switch (Res2.StringResult)
{
case "Line":
bCurve = false;
Bulge = 0;
goto LineSkip;
case "Second":
PromptPointResult SecondPtres = ed.GetPoint
("\nPick the second point:");
if (SecondPtres.Status == PromptStatus.Cancel)
return;
if (SecondPtres.Status == PromptStatus.OK)
{
Point3d P3d = SecondPtres.Value;
SecondPtres = null;
jig = new PolyArcJig(Norm, iVertex, Res1.Value,
P3d.GetAsVector(), pn, Elev, true);
//new Vector3d(P3d.X, P3d.Y, P3d.Z), pn, true);
if (ed.Drag(jig).Status == PromptStatus.OK)
Res2 = jig.Res();
if (Res2.Status == PromptStatus.Cancel)
return;
}
break;
}
}
if (Res2.Status == PromptStatus.OK)
{
Arc oArc = (Arc)jig.GetEntity();
Bulge = Math.Tan(oArc.TotalAngle / 4);
Bulge = Bulge * (int)jig.MinusPlus();
bCurve = true;
}
} //End "Arc" || bCurve
if (Res2.StringResult == "Close")
{
oPline = (Polyline)tr.GetObject(id, OpenMode.ForWrite);
oPline.Closed = true;
tr.Commit();
tr.Dispose();
return;
}
else if (Res2.StringResult == "Undo")
{
oPline = (Polyline)tr.GetObject(id, OpenMode.ForWrite);
if (oPline.NumberOfVertices > 1)
{
bCurve = oPline.GetBulgeAt(iVertex - 1) != 0;
oPline.RemoveVertexAt(iVertex);
tr.Commit();
iVertex = iVertex - 2;
BasePt = oPline.GetPoint3dAt(iVertex + 1).TransformBy(ucs.Inverse());
}
else
{
iVertex = iVertex - 1;
}
goto Undone;
}
// Points from jig are already in wcs
if (bCurve)
{
P = Res2.Value.Convert2d(pn);
}
else
{
P = Res2.Value.TransformBy(ucs).Convert2d(pn);
}
if (makepline)
{
oPline.AddVertexAt(1, P, Bulge, 0, 0);
oPline.SetBulgeAt(0, Bulge);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
btr.AppendEntity(oPline);
tr.AddNewlyCreatedDBObject(oPline, true);
tr.Commit();
id = oPline.ObjectId;
makepline = false;
}
else
{
oPline = (Polyline)tr.GetObject(id, OpenMode.ForWrite);
oPline.AddVertexAt(iVertex + 1, P, Bulge, 0, 0);
oPline.SetBulgeAt(iVertex, Bulge);
tr.Commit();
}
BasePt = Res2.Value;
Undone:
iVertex++;
Res1 = Res2;
}
}
catch (System.Exception ex)
{
ed.WriteMessage("\nError: " + ex.Message);
tr.Abort();
}
finally
{
if (tr != null) tr.Dispose();
}
}
}//End PlineDraw
#endregion
}
}
}