//Polylines/////////////////////////////////////////////////////////////////////////////
public class PlineJiggy
{
public class PolyArcJiggy
{
public class PolyArcJig : EntityJig
{
public Point2d startP, endP, SecondPt2d;
private Vector3d Norm, ViewDir, firstderiv;
private double Elev;
private Plane pn;
private Point3d BasePt, SecondPt, Cen3d;
public Point3d endP3d;
public double bulge;
public int i, iVertex;
private PromptPointResult dres;
private bool bCurve, bSecondPt;
private Matrix3d ucs;
private string jPrompts, keywords;
private Polyline oPline;
public PolyArcJig(double El, Vector3d norm, Point3d basept,
Point2d P, Matrix3d Ucs, Plane Pn, Vector3d Viewdir, Vector3d FirstDeriv,
string jigPrompts, string Keywords, bool BCurve, bool bSecond)
: base(new Polyline())
{
ucs = Ucs; pn = Pn; ViewDir = Viewdir;
Norm = norm; Elev = El;
jPrompts = jigPrompts; keywords = Keywords;
BasePt = basept; startP = P;
bCurve = BCurve;
bSecondPt = bSecond;
oPline = (Polyline)Entity;
oPline.Elevation = El;
oPline.Normal = norm;
oPline.AddVertexAt(0, startP, 0, 0, 0);
oPline.AddVertexAt(1, startP, 0, 0, 0);
if (bCurve)
{
firstderiv = FirstDeriv;
if (bSecondPt)
{
SecondPt = new Point3d(firstderiv.ToArray());
SecondPt2d = SecondPt.Convert2d(pn);
}
}
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
JigPromptPointOptions jigOpts = new JigPromptPointOptions();
jigOpts.UserInputControls = (UserInputControls.Accept3dCoordinates) |
UserInputControls.NullResponseAccepted;
if (bSecondPt | jPrompts == "\nSpecify end point of arc:")
jigOpts.Message = jPrompts;
else
jigOpts.SetMessageAndKeywords(jPrompts, keywords);
jigOpts.BasePoint = BasePt;
jigOpts.UseBasePoint = true;
dres = prompts.AcquirePoint(jigOpts);
if (dres.Status == PromptStatus.None)
return SamplerStatus.Cancel;
if (dres.Status == PromptStatus.Keyword)
{
return SamplerStatus.OK;
}
//CheckPoint(Elev, ucs, ViewDir, dres.Value.TransformBy(ucs.Inverse()), ref endP3d);
Point3d p3d = dres.Value;
double mult = (Elev - (p3d.X * Norm.X) - (p3d.Y * Norm.Y) - (p3d.Z * Norm.Z)) /
((ViewDir.X * Norm.X) + (ViewDir.Y * Norm.Y) + (ViewDir.Z * Norm.Z));
endP3d = p3d.Add(ViewDir.MultiplyBy(mult));
Point2d endPointTemp = endP3d.Convert2d(pn);
if (endPointTemp != endP)
{
endP = endPointTemp;
}
else
{
return SamplerStatus.NoChange;
}
if (dres.Status == PromptStatus.Cancel)
return SamplerStatus.Cancel;
else
return SamplerStatus.OK;
}//End sampler
protected override bool Update()
{
try
{
if (bCurve)
{
Point2d Cen;
if (bSecondPt)
{
Cen3d = Util.MyMath.CenterFrom3Pts(BasePt, SecondPt, endP3d);
Cen = Cen3d.Convert2d(pn);
double Ang = (startP - Cen).GetAngleTo(endP - Cen);
int isCenterLeft = Util.MyMath.isLeft(startP, endP, Cen);
int isSecondPtLeft = Util.MyMath.isLeft(startP, endP, SecondPt2d);
////-1 means P is right of the line (CCW)
if (isCenterLeft == isSecondPtLeft)
Ang = 2 * Math.PI - Ang;
//arc angle > 180 deg
bulge = Math.Tan( Ang / 4);
if (isSecondPtLeft == 1) bulge = -bulge;
}
else
{
Vector2d vCen = firstderiv.Convert2d(pn);
double Ang = vCen.GetAngleTo(startP.GetVectorTo(endP));
bulge = Math.Tan(Ang / 2);
if (Util.MyMath.isLeft(startP, endP, startP.Add(vCen)) == 1)
bulge = -bulge;
}
((Polyline)Entity).SetBulgeAt(0, bulge);
}
((Polyline)Entity).SetPointAt(1, endP);
}
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
public static bool CheckPoint(double Elev, Matrix3d ucs, Vector3d v, Point3d ucsPt, ref Point3d p3d)
{
//Input the point in ucs and the byref output is in wcs
Point3d P = ucsPt;
if (Math.Abs(P.Z) < 0.000001)
{
P = new Point3d(P.X, P.Y, 0);
p3d = P.TransformBy(ucs);
return false;
}
p3d = ucsPt.TransformBy(ucs);
Vector3d Norm = ucs.CoordinateSystem3d.Zaxis;
double mult = (Elev - (p3d.X * Norm.X) - (p3d.Y * Norm.Y) - (p3d.Z * Norm.Z)) /
((v.X * Norm.X) + (v.Y * Norm.Y) + (v.Z * Norm.Z));
p3d = p3d.Add(v.MultiplyBy(mult));
return true;
}
#region Command Declarations
[CommandMethod("DPl")]
public void PlineDraw()
{
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
Matrix3d ucs = ed.CurrentUserCoordinateSystem;
CoordinateSystem3d cs = ucs.CoordinateSystem3d;
Vector3d Norm = cs.Zaxis;
Plane pn = new Plane(cs.Origin, Norm);
double Elev = -pn.Coefficients.D;
pn = new Plane(Point3d.Origin, Norm);
Polyline oPline = new Polyline();
ViewTableRecord vtr = ed.GetCurrentView();
Vector3d Viewdirection = vtr.ViewDirection.GetNormal();
double lastAngle = (double)acadApp.GetSystemVariable("LASTANGLE");
Vector3d FirstDeriv = new Vector3d(1, Math.Tan(lastAngle), 0);
//Get the first point
PromptPointResult Pres = ed.GetPoint("\nSpecify start point:");
if (Pres.Status != PromptStatus.OK) return;
Point3d BasePt = Pres.Value.TransformBy(ucs);
Point2d startP = BasePt.Convert2d(pn);
Point2d EndPt;
oPline.Normal = Norm;
oPline.Elevation = Elev;
oPline.AddVertexAt(0, startP, 0, 0, 0);
int iVertex = 1;
PromptResult res;
string prompt = "\nSpecify next point or [Arc]:";
string keywords = "Arc";
bool bCurve = false, bSecond = false;
ObjectId id = ObjectId.Null;
double Bulge = 0;
PolyArcJig jig;
Transaction tr = null;
do
{
jig = new PolyArcJig(Elev, Norm, BasePt, startP, ucs, pn,
Viewdirection, FirstDeriv, prompt, keywords, bCurve, bSecond);
res = ed.Drag(jig);
if (res.Status == PromptStatus.Cancel) return;
if (res.Status == PromptStatus.Keyword)
{
using (tr = db.TransactionManager.StartTransaction())
{
switch (res.StringResult)
{
//case "Angle":
// //Todo
// break;
case "Arc":
prompt =
"\nSpecify next point or [Close/Line/Second pt/Undo]:";
keywords = "Close Line Second Undo";
bCurve = true;
if (iVertex > 1)
FirstDeriv = oPline.GetFirstDerivative
(oPline.NumberOfVertices - 1);
break;
case "Close":
{
oPline = (Polyline)tr.GetObject(id, OpenMode.ForWrite);
if (oPline.GetPoint2dAt(0) == oPline.GetPoint2dAt(iVertex - 1))
{
iVertex = iVertex - 1;
Bulge = oPline.GetBulgeAt(iVertex);
oPline.RemoveVertexAt(iVertex);
}
else
Bulge = 0;
oPline.Closed = true;
oPline.SetBulgeAt(iVertex - 1, Bulge);
tr.Commit();
return;
}
case "Second":
prompt = "\nSpecify second point on arc:";
bCurve = false;
bSecond = true;
break;
case "Undo":
oPline = (Polyline)tr.GetObject(id, OpenMode.ForWrite);
if (oPline.NumberOfVertices > 2)
{
bCurve = oPline.GetBulgeAt(iVertex - 1) != 0;
oPline.RemoveVertexAt(iVertex - 1);
tr.Commit();
iVertex = iVertex - 1;
startP = oPline.GetPoint2dAt(iVertex - 1);
BasePt = oPline.GetPoint3dAt(iVertex - 1);
FirstDeriv = oPline.GetFirstDerivative
(oPline.NumberOfVertices - 1);
}
else
{
iVertex = iVertex - 1;
}
goto Skip;
//break;
default:
prompt = "\nSpecify next point or [Arc/Close/Second pt/Undo]:";
keywords = "Arc Close Second Undo";
bCurve = false;
break;
}
tr.Commit();
}
}
if (res.Status == PromptStatus.OK)
{
if (bSecond)
{
prompt = "\nSpecify end point of arc:";
FirstDeriv = jig.endP3d.GetAsVector();
if (bCurve)
{
prompt = "\nSpecify next point or [Close/Line/Second pt/Undo]:";
keywords = "Close Line Second Undo";
bSecond = false;
}
else
{
//Util.AddEnt.Point(jig.endP3d,1);
bCurve = true;
goto Skip;
}
}
using (tr = db.TransactionManager.StartTransaction())
{
EndPt = jig.endP;
Bulge = jig.bulge;
if (iVertex == 1)
{
oPline.AddVertexAt(1, EndPt, Bulge, 0, 0);
oPline.SetBulgeAt(0, Bulge);
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject
(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
btr.AppendEntity(oPline);
tr.AddNewlyCreatedDBObject(oPline, true);
id = oPline.ObjectId;
prompt =
"\nSpecify next point or [Arc/Close/Line/Second pt/Undo]:";
keywords = "Arc Close Line Second Undo";
FirstDeriv = oPline.GetFirstDerivative(1);
}
else
{
oPline = tr.GetObject(id, OpenMode.ForWrite) as Polyline;
oPline.AddVertexAt(iVertex, EndPt, Bulge, 0, 0);
oPline.SetBulgeAt(iVertex - 1, Bulge);
FirstDeriv = oPline.GetFirstDerivative(oPline.NumberOfVertices - 1);
}
BasePt = oPline.GetPoint3dAt(iVertex);
startP = EndPt;
iVertex++;
tr.Commit();
}
}
Skip: ;
} while (res.Status == PromptStatus.OK || res.Status == PromptStatus.Keyword);
} //End PlineDraw
#endregion
}
} //End PlineDraw