Author Topic: Offset  (Read 6654 times)

0 Members and 1 Guest are viewing this topic.

Bryco

  • Water Moccasin
  • Posts: 1883
Offset
« on: January 04, 2010, 06:38:29 PM »
Man, this is trickier than I thought. I am making a simple function to offset a curve and place the offset object on the defpoints layer.
I've never thought how cad decides which side of arc gets offset  by a picked  point, but if it is between rays made by the start and end parameters and on the center side of the arc it will offset to the smaller side.
Here's a snip, I am hoping others do this a better way as I don't really like all the conversions to 2d
Code: [Select]
else if (curve is Arc)
                    {
                        Arc arc = (Arc)curve;
                        rad = arc.Radius;
                        dist = arc.Center.DistanceTo(p);
                        Point2d p1, p2, p3,p4;
                        p1 = arc.StartPoint.Convert2d(plane);
                        p2 = arc.EndPoint.Convert2d(plane);
                        p3 = p.Convert2d(plane);
                        p4 = arc.Center.Convert2d(plane);
                        double ang = arc.Center.GetVectorTo(p).AngleOnPlane(plane);
                        if (ang < arc.EndAngle && ang > arc.StartAngle)
                        {
                            if (dist < rad) offset = -offset;
                        }
                        else
                        {
                            double d90 = Math.PI * 0.5;
                            Vector2d v1 = (p1 - p4).RotateBy(d90).GetNormal();
                            Vector2d v2 = (p2 - p4).RotateBy(-d90).GetNormal();   
                            double multiplier = (p1 - p2).Length / (v2 - v1).Length;
                            p4 = p1.Add(v1.MultiplyBy(multiplier));
                            ang = (p3 - p4).Angle;
                            if (ang > (p2 - p4).Angle && ang < (p1 - p4).Angle)
                                offset = -offset;                 
                        }
         
                        if (offset < 0)
                        {
                            if (arc.Radius < -offset)
                            {
                                MessageBox.Show("The offset can not be greater than the arc radius, exiting:");
                                return;
                            }
                        }
                        Arc newArc = new Arc(arc.Center, arc.Normal, arc.Radius + offset, arc.StartAngle, arc.EndAngle);
                        newArc.Layer = sLayer;
                        space.AppendEntity(newArc);
                        tr.AddNewlyCreatedDBObject(newArc, true);

                    }

                    tr.Commit();


The polyline and spline are going to get really difficult

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8709
  • AKA Daniel
Re: Offset
« Reply #1 on: January 04, 2010, 06:51:50 PM »
why not use getOffsetCurves?

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Offset
« Reply #2 on: January 04, 2010, 06:59:11 PM »
I still have to know which curve to pick  ( I will be using getOffsetCurves for plines and splines)

sinc

  • Guest
Re: Offset
« Reply #3 on: January 04, 2010, 07:55:50 PM »
Man, this is trickier than I thought. I am making a simple function to offset a curve and place the offset object on the defpoints layer.

BTW, you know that placing drawing objects on DEFPOINTS is discouraged, right?

This is what Autodesk says on the matter:

Quote from: Autodesk
If you have objects that you want to put on a non-plot layer, you no longer use the Defpoints layer for this. Instead, create the a layer named 'no-plot' or something similarly named, and this will allow you to use this layer instead of the Defpoints layer for no-plot objects. In the Layer Manager, use the Plot/No Plot option to set up one or more layers that you do not want to plot. The reason for doing this is because when you put objects on the Defpoints layer, other than the definition points of a dimension for which this layer was designed for, and you run the Audit command, the Audit command will create a layer called $AUDIT-BAD-LAYER. Audit will then put all the objects you had on the defpoints layer on this layer. Your objects will therefore not be on a no-plot layer any longer. If you instead create the no-plot layer to begin with you will save yourself some headaches down the road.It is still bad practice to place objects on Defpoints, just create a no plot layer.

Although to be fair, I've created objects on DEFPOINTS and run AUDIT, and it doesn't create an $AUDIT-BAD-LAYER layer.  So there seems to be more going on than Autodesk says in this statement.

But anyway...  Posting this for info purposes only; take it as you will.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8709
  • AKA Daniel
Re: Offset
« Reply #4 on: January 04, 2010, 07:59:47 PM »
I still have to know which curve to pick  ( I will be using getOffsetCurves for plines and splines)

Doh! sorry, I hadn't had my coffee yet  :wink:

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Offset
« Reply #5 on: January 04, 2010, 08:11:03 PM »
Sinc- I agree, and have recently done this. I also have had a problem w/ turning layer zero off and then finding layer defpoints is uneditable.
I just used the old commandname I have used in vba. Now I am changing over.

Daniel, no worries there you do a lot better than me before you've had your coffee. What I posted doesn't always work anyway. Angles I hate them, I need to compare vectors and I haven't figured that out yet.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8709
  • AKA Daniel
Re: Offset
« Reply #6 on: January 05, 2010, 01:42:09 AM »
would something like this work for you?

Code: [Select]
  [CommandMethod("doit")]
  static public void doit()
  {
   Editor editor = Application.DocumentManager.MdiActiveDocument.Editor;
   Database database = HostApplicationServices.WorkingDatabase;
   PromptEntityResult per = editor.GetEntity("\nGet it: ");
   PromptPointResult ppr = editor.GetPoint("\nPick Side: ");

   AcDb.TransactionManager manager = database.TransactionManager;
   using (Transaction transaction = manager.StartTransaction())
   {
    if (per.Status == PromptStatus.OK)
    {
     DBObject curve = transaction.GetObject(per.ObjectId, OpenMode.ForRead);
     if (curve is Arc)
     {
      Arc arc = (Arc)curve;
      CircularArc3d carc = new CircularArc3d(arc.Center,arc.Normal, arc.Radius);
      if (!carc.IsInside(ppr.Value))
       editor.WriteMessage("\n Offset is Positive");
      else
       editor.WriteMessage("\n Offset is Negative");
     }
    }
   }
  }


It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8709
  • AKA Daniel
Re: Offset
« Reply #7 on: January 05, 2010, 09:23:37 AM »
for testing

Code: [Select]
public static class Commands
 {
  [CommandMethod("doit")]
  static public void doit()
  {
   Editor editor = Application.DocumentManager.MdiActiveDocument.Editor;
   Database database = HostApplicationServices.WorkingDatabase;
   PromptEntityResult per = editor.GetEntity("\nGet it: ");
   PromptDoubleResult pdr = editor.GetDistance("\nGet Distance: ");
   PromptPointResult ppr = editor.GetPoint("\nPick Side: ");

   AcDb.TransactionManager manager = database.TransactionManager;
   using (Transaction transaction = manager.StartTransaction())
   {
    if (per.Status == PromptStatus.OK)
    {
     DBObjectCollection dbo = null;
     DBObject curve = transaction.GetObject(per.ObjectId, OpenMode.ForRead);
     if (curve is Arc)
     {
      Arc arc = (Arc)curve;
      CircularArc3d carc = new CircularArc3d(arc.Center, arc.Normal, arc.Radius);

      BlockTableRecord blockTableRecord =
       transaction.GetObject(database.CurrentSpaceId, OpenMode.ForWrite)
       as BlockTableRecord;

      if (!carc.IsInside(ppr.Value))
       dbo = arc.GetOffsetCurves(pdr.Value);
      else
       dbo = arc.GetOffsetCurves(-Math.Abs(pdr.Value));

      foreach (Entity e in dbo)
      {
       blockTableRecord.AppendEntity(e);
       transaction.AddNewlyCreatedDBObject(e, true);
      }
     }
    }
    transaction.Commit();
   }
  }
 }
}

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Offset
« Reply #8 on: January 05, 2010, 09:25:17 AM »
Good try Daniel but that only checks for a point being with an arcs circle

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8709
  • AKA Daniel
Re: Offset
« Reply #9 on: January 05, 2010, 09:36:22 AM »
I know, it's the same behavior as AutoCAD's offset command right?
« Last Edit: January 05, 2010, 09:51:52 AM by Daniel »

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Offset
« Reply #10 on: January 05, 2010, 10:07:23 AM »
No autocad offset is fairly complicated

SEANT

  • Bull Frog
  • Posts: 345
Re: Offset
« Reply #11 on: January 05, 2010, 03:48:12 PM »
The Autodesk.AutoCAD.Geometry.OffsetCurve2d is a bit more descriptive on how the offset procedure works.  I imagine they would employ the same comparison method for the DatabaseServices.Curve.

It essentially amounts to the same thing as the ray comparison.


I borrowed a bit of code from some previous posts to demonstrate what I think the description is implying.


Code: [Select]
  static public void doit()
  {
   Editor editor = Application.DocumentManager.MdiActiveDocument.Editor;
   Database database = HostApplicationServices.WorkingDatabase;
   PromptEntityResult per = editor.GetEntity("\nGet it: ");
   PromptDoubleResult pdr = editor.GetDistance("\nGet Distance: ");
   PromptPointResult ppr = editor.GetPoint("\nPick Side: ");

   AcDB.TransactionManager manager = database.TransactionManager;
   using (Transaction transaction = manager.StartTransaction())
   {
    if (per.Status == PromptStatus.OK)
    {
     DBObjectCollection dbo = null;
     DBObject curve = transaction.GetObject(per.ObjectId, OpenMode.ForRead);
     if (curve is Arc)
     {
      Arc arc = (Arc)curve;
      Point3d PickPt = ppr.Value;
      Point3d ClosestPt = arc.GetClosestPointTo(ppr.Value, false);
      Vector3d v3d = arc.GetFirstDerivative(ClosestPt);
      v3d = new Vector3d(-v3d.Y, v3d.X, v3d.Z);

      BlockTableRecord blockTableRecord =
       transaction.GetObject(database.CurrentSpaceId, OpenMode.ForWrite)
       as BlockTableRecord;
         Double ang = Math.Abs(v3d.GetAngleTo(ClosestPt.GetVectorTo(PickPt)));

      if (ang > Math.PI/2)
       dbo = arc.GetOffsetCurves(pdr.Value);
      else
       dbo = arc.GetOffsetCurves(-Math.Abs(pdr.Value));

      foreach (Entity e in dbo)
      {
       blockTableRecord.AppendEntity(e);
       transaction.AddNewlyCreatedDBObject(e, true);
      }
     }
    }
    transaction.Commit();
   }
  }
« Last Edit: January 05, 2010, 03:51:55 PM by SEANT »
Sean Tessier
AutoCAD 2016 Mechanical

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Offset
« Reply #12 on: January 05, 2010, 04:32:30 PM »
So far this is working very well thanks Sean. Nice work.

Glenn R

  • Guest
Re: Offset
« Reply #13 on: January 05, 2010, 05:52:14 PM »
BTW, layer 0 and defpoints are 'linked' for display purposes...have been for years.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8709
  • AKA Daniel
Re: Offset
« Reply #14 on: January 05, 2010, 06:20:42 PM »
No autocad offset is fairly complicated

Doh! you're Right!   :oops: