I created a rectangle using draw line (i am wirking on Autocad 2010)
Now I want to create 4 fillets at each corner with some radius using vb.net
Please somebody help me please
Thanks
dipak
Edited by: dip_nik on Jan 13, 2010 11:22 AM
This one is a bit tricky but working for mein A2008
(spell all prompts)
{code}
using System;
using System.Text;
using System.Collections;
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;
using (tr)
{
try
{
// Prompt for the fillet radius
PromptDoubleOptions pdo = new PromptDoubleOptions("\nEnter the fillet radius: ");
pdo.AllowZero = false;
pdo.AllowNegative = false;
pdo.AllowNone = false;
PromptDoubleResult pdr = ed.GetDouble(pdo);
if (pdr.Status != PromptStatus.OK)
return;
double rad = pdr.Value;
// Prompt for the lines to fillet
PromptEntityOptions peo = new PromptEntityOptions("\nSelect first line:");
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
return;
ObjectId fid = per.ObjectId;
peo.Message = "\nSelect second line:";
per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
return;
ObjectId sid = per.ObjectId;
// get entities
Entity ent1 = tr.GetObject(fid, OpenMode.ForRead) as Entity;
Entity ent2 = tr.GetObject(sid, OpenMode.ForRead) as Entity;
// cast entites as lines
Line line1 = ent1 as Line;
Line line2 = ent2 as Line;
Point3dCollection intpts = new Point3dCollection();
// get intersection between lines
line1.IntersectWith(line2, Intersect.OnBothOperands, intpts, 0, 0);
if (intpts.Count != 1)
{
acadApp.ShowAlertDialog("Lines are colinear or does not intersects");
return;
}
Point3d ip = intpts[0];
Point3d midp1;
Point3d midp2;
// compare points
if (!(line1.StartPoint.Equals(ip)))
{
line1.UpgradeOpen();
if (!(line2.StartPoint.Equals(ip)))
{
line2.UpgradeOpen();
line2.EndPoint = line2.StartPoint;
line2.StartPoint = ip;
}
midp2 = line2.GetPointAtDist(rad);
// get point on bisector
Point3d midp = new Point3d(
(midp1.X + midp2.X) / 2.0,
(midp1.Y + midp2.Y) / 2.0,
(midp1.Z + midp2.Z) / 2.0);
// get angles along lines from intersection
double ang1 = AngleFromX(ip, midp1);
double ang2 = AngleFromX(ip, midp2);
// get bisector angle
double ang = AngleFromX(ip, midp);
// calculate angle between lines
double angc = Math.Abs(ang2 - ang1);
// get a half of them
double bis = angc / 2.0;
// calculate hypotenuse
double hyp = rad / Math.Sin(bis);
// calculate center point of filleting arc
Point3d cp = PolarPoint(ip, ang, hyp);
// calculate another leg of a triangle
double cat = Math.Sqrt((Math.Pow(hyp, 2)) - (Math.Pow(rad, 2)));
// calculate center point on arc
Point3d pa = PolarPoint(ip, ang, hyp - rad);
// calculate start point of arc
Point3d ps = PolarPoint(ip, ang1, cat);
// calculate end point of arc
Point3d pe = PolarPoint(ip, ang2, cat);
// define arc
Arc arc = new Arc();
// check on direction of points
if (isLeft(midp2, ip, midp1))
{
arc = new Arc(cp, rad, AngleFromX(cp, pe), AngleFromX(cp, ps));
Here is a link that I personally find useful in converting code from C# to VB.Net and vice-versa. Some basic things will need to be fixed if you get some compile errors.
'/// '/// Polar point // credit to Tony Tanzillo '/// Public Shared Function PolarPoint(ByVal basepoint As Point3d, ByVal angle As Double, ByVal distance As Double) As Point3d
End Function '/// '/// Public Shared Function AngleFromX(ByVal pt1 As Point3d, ByVal pt2 As Point3d) As Double
Dim ang As Double Dim vec As Vector3d Dim ucsplane As Plane
ucsplane = New Plane(New Point3d(0, 0, 0), New Vector3d(0, 0, 1))
vec = pt2 - pt1
ang = vec.AngleOnPlane(ucsplane)
Return ang
End Function '/// '/// isleft function (edited) // credit to Bryco '/// Public Shared Function isLeft(ByVal spt As Point3d, ByVal ept As Point3d, ByVal apt As Point3d) As Boolean
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using static System.Math;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
[assembly: CommandClass(typeof(Fillet3D.Commands))]
namespace Fillet3D
{
public class Commands
{
double radius = 0.0;
[CommandMethod("TEST")]
public void Test()
{
var doc = AcAp.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var pdo = new PromptDistanceOptions("\nEnter the fillet radius: ");
pdo.DefaultValue = radius;
pdo.AllowNegative = false;
pdo.AllowNone = true;
pdo.UseDefaultValue = true;
var pdr = ed.GetDistance(pdo);
if (pdr.Status != PromptStatus.OK) return;
radius = pdr.Value;
var peo = new PromptEntityOptions("\nSelect the first line: ");
peo.SetRejectMessage("\nSelected object is not a line.");
peo.AddAllowedClass(typeof(Line), true);
var per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
var id1 = per.ObjectId;
var pp1 = ed.Snap("_near", per.PickedPoint).TransformBy(ed.CurrentUserCoordinateSystem);
peo.Message = "\nSelect the second line: ";
per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
var id2 = per.ObjectId;
var pp2 = ed.Snap("_near", per.PickedPoint).TransformBy(ed.CurrentUserCoordinateSystem);
using (var tr = db.TransactionManager.StartTransaction())
{
// open the lines
var line1 = (Line)tr.GetObject(id1, OpenMode.ForRead);
var line2 = (Line)tr.GetObject(id2, OpenMode.ForRead);
// get the intersection
var pts = new Point3dCollection();
line1.IntersectWith(line2, Intersect.ExtendBoth, pts, IntPtr.Zero, IntPtr.Zero);
if (pts.Count != 1)
{
ed.WriteMessage("\nSelected lines do not intersect.");
return;
}
var inters = pts[0];
var sp1 = line1.StartPoint;
var ep1 = line1.EndPoint;
var sp2 = line2.StartPoint;
var ep2 = line2.EndPoint;
// get the farest points from intersection on the picked side of both lines
Func<Point3d, Point3d, Point3d, Point3d> getFarest = (sp, ep, pp) =>
{
var dir = inters.GetVectorTo(pp);
if (!inters.GetVectorTo(sp).IsCodirectionalTo(dir)) return ep;
if (!inters.GetVectorTo(ep).IsCodirectionalTo(dir)) return sp;
if (inters.DistanceTo(sp) < inters.DistanceTo(ep)) return ep;
return sp;
};
var fp1 = getFarest(sp1, ep1, pp1);
var fp2 = getFarest(sp2, ep2, pp2);
// if radius == 0, just trim/extend the lines
if (radius == 0.0)
{
line1.UpgradeOpen();
if (sp1.IsEqualTo(line1.StartPoint))
line1.EndPoint = inters;
else
line1.StartPoint = inters;
line2.UpgradeOpen();
if (sp2.IsEqualTo(line2.StartPoint))
line2.EndPoint = inters;
else
line2.StartPoint = inters;
}
// compute the fillet
else
{
// 2D work in the plane defined by the two lines
var normal = (fp1 - inters).CrossProduct(fp2 - inters);
var plane = new Plane(inters, normal);
var v1 = fp1.Convert2d(plane).GetAsVector();
var v2 = fp2.Convert2d(plane).GetAsVector();
double angle = v1.GetAngleTo(v2) / 2.0;
var dist = radius / Tan(angle);
if (v1.Length <= dist || v2.Length <= dist)
{
ed.WriteMessage("\nRadius too large to fillet the selected lines.");
return;
}
double hyp = radius / Sin(angle);
var center = new Point2d(hyp * Cos(angle + v1.Angle), hyp * Sin(angle + v1.Angle));
var p1 = Point2d.Origin + v1.GetNormal() * dist;
var p2 = Point2d.Origin + v2.GetNormal() * dist;
var a1 = center.GetVectorTo(p1).Angle;
var a2 = center.GetVectorTo(p2).Angle;
// back to 3D
Func<Point2d, Point3d> convert3d = (pt) =>
new Point3d(pt.X, pt.Y, 0.0).TransformBy(Matrix3d.PlaneToWorld(plane));
var arc = new Arc(new Point3d(center.X, center.Y, 0.0), radius, a2, a1);
arc.TransformBy(Matrix3d.PlaneToWorld(plane));
var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
curSpace.AppendEntity(arc);
tr.AddNewlyCreatedDBObject(arc, true);
line1.UpgradeOpen();
line1.StartPoint = convert3d(p1);
line1.EndPoint = fp1;
line2.UpgradeOpen();
line2.StartPoint = fp2;
line2.EndPoint = convert3d(p2);
}
tr.Commit();
}
}
}
}
Everything will work just as you expect it to, unless your expectations are incorrect. ~ kdub Sometimes the question is more important than the answer. ~ kdub
NZST UTC+12 : class keyThumper<T> : Lazy<T>; another Swamper
Delegates are an alternative to local functions which are coming with the C# 7 as tuples and pattern matching.
C# get closer to F# at each new version...
F# code
namespace Fillet3d
open System
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Geometry
open Autodesk.AutoCAD.Runtime
type AcAp = Autodesk.AutoCAD.ApplicationServices.Application
type Command () =
let mutable radius = 0.0
[<CommandMethod("Test")>]
member x.test () =
let doc = AcAp.DocumentManager.MdiActiveDocument
let db = doc.Database
let ed = doc.Editor
let pdo = PromptDistanceOptions("\nSpecify the radius: ")
pdo.DefaultValue <- radius
pdo.UseDefaultValue <- true
pdo.AllowNegative <- false
let pdr = ed.GetDistance(pdo)
if (pdr.Status = PromptStatus.OK) then
radius <- pdr.Value
ed.WriteMessage("\nRadius = {0}", radius)
let peo = PromptEntityOptions("\nSelect the first line: ")
peo.SetRejectMessage("\nSelected object is not a line.")
peo.AddAllowedClass(typeof<Line>, true)
let per = ed.GetEntity(peo)
if (per.Status = PromptStatus.OK) then
let id1 = per.ObjectId
let pp1 = ed.Snap("_near", per.PickedPoint).TransformBy(ed.CurrentUserCoordinateSystem)
peo.Message <- "\nSelect the second line: "
let per = ed.GetEntity(peo)
if (per.Status = PromptStatus.OK) then
let id2 = per.ObjectId
let pp2 = ed.Snap("_near", per.PickedPoint).TransformBy(ed.CurrentUserCoordinateSystem)
use tr = db.TransactionManager.StartTransaction()
// open the lines
let line1 = tr.GetObject(id1, OpenMode.ForRead) :?> Line
let line2 = tr.GetObject(id2, OpenMode.ForRead) :?> Line
// get the intersection
let pts = new Point3dCollection()
line1.IntersectWith(line2, Intersect.ExtendBoth, pts, IntPtr.Zero, IntPtr.Zero)
if (pts.Count = 0) then
ed.WriteMessage("\nSelected lines do not intersect.")
else
let inters = pts.[0]
// get the farest points from intersection on the picked side of both lines
let getFarest sp ep pp =
let dir = pp - inters
if not ((sp - inters).IsCodirectionalTo(dir)) then ep
elif not ((ep - inters).IsCodirectionalTo(dir)) then sp
elif inters.DistanceTo(sp) < inters.DistanceTo(ep) then ep
else sp
let fp1 = getFarest line1.StartPoint line1.EndPoint pp1
let fp2 = getFarest line2.StartPoint line2.EndPoint pp2
// if radius equals 0.0, just trim or extend the lines
if radius = 0.0 then
let trimExtend (line: Line) fp =
line.UpgradeOpen()
if line.StartPoint.IsEqualTo(fp)
then line.EndPoint <- inters
else line.StartPoint <- inters
trimExtend line1 fp1
trimExtend line2 fp2
else // compute the fillet
// 2D work in the plane defined by the 2 lines
let norm = (fp1 - inters).CrossProduct(fp2 - inters)
let plane = new Plane(inters, norm)
let v1 = fp1.Convert2d(plane).GetAsVector()
let v2 = fp2.Convert2d(plane).GetAsVector()
let ang = v1.GetAngleTo(v2) / 2.
let dist = radius / tan ang
if (v1.Length <= radius || v2.Length <= radius) then
ed.WriteMessage("\nRadius too large too fillet the lines.")
else
let hyp = radius / sin ang
let cen = Point2d(hyp * cos (ang + v1.Angle), hyp * sin (ang + v1.Angle))
let pointAngle (v : Vector2d) =
let p = Point2d.Origin + v.GetNormal() * dist
(p, (p - cen).Angle)
let (p1, a1) = pointAngle v1
let (p2, a2) = pointAngle v2
// back to 3D
let arc = new Arc(Point3d(cen.X, cen.Y, 0.0), radius, a2, a1)
arc.TransformBy(Matrix3d.PlaneToWorld(plane))
let space = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord
space.AppendEntity(arc) |> ignore
tr.AddNewlyCreatedDBObject(arc, true)
let convert3d (pt : Point2d) =
Point3d(pt.X, pt.Y, 0.0).TransformBy(Matrix3d.PlaneToWorld(plane))
let trimExtend (line : Line) fp p =
line.UpgradeOpen()
if line.StartPoint.IsEqualTo(fp)
then line.EndPoint <- convert3d p
else line.StartPoint <- convert3d p
trimExtend line1 fp1 p1
trimExtend line2 fp2 p2
tr.Commit()