using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
[assembly
: CommandClass
(typeof(PolylineFillet
.CommandMethods))]
namespace PolylineFillet
{
public class CommandMethods
{
[CommandMethod("Test", CommandFlags.Modal)]
public void Test()
{
Document doc = AcAp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptDistanceOptions pdo
= new PromptDistanceOptions
("\nFillet radius: "); pdo.AllowZero = false;
pdo.AllowNegative = false;
PromptDoubleResult pdr = ed.GetDistance(pdo);
if (pdr.Status != PromptStatus.OK)
return;
double radius = pdr.Value;
PromptEntityOptions peo
= new PromptEntityOptions
("\nSelect a polyline: "); peo.SetRejectMessage("Not a polyline.");
peo
.AddAllowedClass(typeof(Polyline
),
true); PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Polyline pline = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForWrite);
FilletAll(pline, radius);
tr.Commit();
}
}
private void FilletAll(Polyline pline, double radius)
{
int n = pline.Closed ? 1 : 2;
for (int i = 0; i < pline.NumberOfVertices - n; i++)
i += Fillet(pline, radius, i, i + 1);
if (pline.Closed)
Fillet(pline, radius, pline.NumberOfVertices - 1, 0);
}
private int Fillet(Polyline pline, double radius, int index1, int index2)
{
if (pline.GetSegmentType(index1) != SegmentType.Line ||
pline.GetSegmentType(index2) != SegmentType.Line)
return 0;
LineSegment2d seg1 = pline.GetLineSegment2dAt(index1);
LineSegment2d seg2 = pline.GetLineSegment2dAt(index2);
Vector2d vec1 = seg1.StartPoint - seg1.EndPoint;
Vector2d vec2 = seg2.EndPoint - seg2.StartPoint;
double angle = vec1.GetAngleTo(vec2) / 2.0;
double dist = radius / Math.Tan(angle);
if (dist > seg1.Length || dist > seg2.Length)
return 0;
Point2d pt1 = seg1.EndPoint.TransformBy(Matrix2d.Displacement(vec1.GetNormal() * dist));
Point2d pt2 = seg2.StartPoint.TransformBy(Matrix2d.Displacement(vec2.GetNormal() * dist));
double bulge = Math.Tan((Math.PI / 2.0 - angle) / 2.0);
if (Clockwise(seg1.StartPoint, seg1.EndPoint, seg2.EndPoint))
bulge = -bulge;
pline.AddVertexAt(index2, pt1, bulge, 0.0, 0.0);
pline.SetPointAt(index2 + 1, pt2);
return 1;
}
private bool Clockwise(Point2d p1, Point2d p2, Point2d p3)
{
return ((p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X)) < 1e-8;
}
}
}