Author Topic: Arc direction?  (Read 5529 times)

0 Members and 1 Guest are viewing this topic.

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Arc direction?
« on: May 30, 2006, 01:11:53 PM »
OK, So I know that all arcs in Acad are created /stored as CCW ars.

For some reason though, I am having brain freeze trying to determine which angle must be the startangle. I have a routine that uses ActiveX to AddArc and the required inputs are CenterPoint Radius StartAngle EndAngle. All this is fine, except I cannot get a consistent result for my arc. Half the time the arc is drawn showing the portion of a circle which excludes my intended arc.

So how do you know/calculate, with certainty, that the start and end angles are in the correct order?

Here are a few of the methods I've attempted:
Code: [Select]
  (if (> ang1 ang2)
    (setq newarc (vlax-invoke space 'addarc newrp r ang2 ang1))
    (setq newarc (vlax-invoke space 'addarc newrp r ang1 ang2))
    )

;;;;;;
  (if (> (* pi 0.5) (angle newend pt) (* pi 1.5))
    (setq newarc (vlax-invoke space 'addarc newrp r ang2 ang1))
    (setq newarc (vlax-invoke space 'addarc newrp r ang1 ang2))
    )

Oh, the line from newend to pt is the chord.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Arc direction?
« Reply #1 on: May 30, 2006, 01:25:37 PM »
From my experience, the arc is drawn counter clockwise.  So if you want the arc to be the top portion of the circle, then you use the start angle on the right side, to the end angle on the left side.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Arc direction?
« Reply #2 on: May 30, 2006, 01:25:57 PM »
Jeff,
Did you see this?
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

LE

  • Guest
Re: Arc direction?
« Reply #3 on: May 30, 2006, 01:27:33 PM »
Jeff;

Here is a portion of code I use in arx, that might give you the idea, what I do is to sort the points by the x value, and after that, I just grab the pair of points with the center like:

Code: [Select]
vector <int>::size_type lth;
lth = _points.size();
int cont = 0;
while (cont < (lth - 1)) {
AcGePoint3d p0 = _points.at(cont);
AcGePoint3d p1 = _points.at(1+cont);
if (!doubleEq(acutDistance(asDblArray(p0),asDblArray(p1)),0.0)) {
double sang = acutAngle(asDblArray(ctr),asDblArray(p0));
double eang = acutAngle(asDblArray(ctr),asDblArray(p1));
double sa,ea;
if (sang < eang) {
sa = sang;
ea = eang;
}else {
sa = eang;
ea = sang;
}
AcDbArc *pNewArc = new AcDbArc(ctr,rad,sa,ea);
AcDbObjectId curSpaceId = acdbCurDwg()->currentSpaceId();  
AcDbBlockTableRecord *pBlkRec = NULL;
if (acdbOpenObject(pBlkRec,curSpaceId,AcDb::kForWrite) == Acad::eOk) {
pBlkRec->appendAcDbEntity(pNewArc);
pBlkRec->close();
pNewArc->close();
}
}
cont = (1 + cont);
}

HTH

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Arc direction?
« Reply #4 on: May 30, 2006, 02:22:35 PM »
Does this help?
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: Arc direction?
« Reply #5 on: May 30, 2006, 03:11:07 PM »
Tim, CAB,
Thanks, but those things I do know. The trick is how to determine which angle is the start and which is the end when you have  the 2 endpoints and the center point.

Luis, thanks, but I thought that I tried what I think your code is doing ( I still can't follow that other code very well).

If it helps, here's what I'm doing (yes, it's in response to a question over at the Acad groups)....given a known point for an arc to pass through, the desired radius, and a line or arc to be tangent to....draw the arc and trim/extend the tangent object. This code works for everything but placing the new arc in the correct direction all the time.

Code: [Select]
(defun c:ptRtan (/ *ACAD* ANG1 ANG2 CIRC DOC INTS NEWARC NEWEND NEWRP
   OFFOBJS P1 P2 PT R SPACE TANEND TANENT TANOBJ TANSTART)
  (if (and (setq r (getdist "\nDesired Radius?: "))
   (setq pt (getpoint "\nPoint to start from: "))
   (setq tanent (entsel "\nLine or arc to be tangent to: "))
   )
    (progn
      (vl-load-com)
      (setq *acad* (vlax-get-acad-object)
    doc (vla-get-activedocument *acad*)
    space (if (= (getvar "cvport") 1)
    (vla-get-paperspace doc)
    (vla-get-modelspace doc)
    )
    )
      (vla-startundomark doc)
      (setq circ (vlax-invoke space 'addcircle pt r))
      (vla-put-visible circ :vlax-false)
      (setq tanobj (vlax-ename->vla-object (car tanent)))
      (setq offobjs (vlax-invoke tanobj 'offset r))
      (if (not (setq ints (vlax-invoke circ 'intersectwith (car offobjs) acExtendOtherEntity)))
(progn
  (vla-delete (car offobjs))
  (setq offobjs (vlax-invoke tanobj 'offset (- r)))
  (setq ints (vlax-invoke circ 'intersectwith (car offobjs) acExtendOtherEntity))
  )
)
      (vla-delete (car offobjs))
      (vla-delete circ)
      (if ints
(progn
  (if (= 3 (length ints))
    (setq newRP ints)
    (progn
      (setq p1 (list (car ints) (cadr ints) (caddr ints))
    p2 (cdddr ints))
      (if (< (distance p1 (cadr tanent)) (distance p2 (cadr tanent)))
(setq newrp p1)
(setq newrp p2)
)
      )
    )
  (setq newend (vlax-curve-getclosestpointto tanobj newrp t)
ang1 (angle newrp pt)
ang2 (angle newrp newend)
tanstart (vlax-get tanobj 'startpoint)
tanend (vlax-get tanobj 'endpoint)
)
  (if (< (distance tanstart newend) (distance tanend newend))
    (if (= (cdr (assoc 0 (entget (car tanent)))) "LINE")
      (vlax-put tanobj 'startpoint newend)
      (vla-put-startangle tanobj (angle (vlax-get tanobj 'center) newend))
      )
    (if (= (cdr (assoc 0 (entget (car tanent)))) "LINE")
      (vlax-put tanobj 'endpoint newend)
      (vla-put-endangle tanobj (angle (vlax-get tanobj 'center) newend))
      )
    )
  (if (< ang1 ang2)
    (setq newarc (vlax-invoke space 'addarc newrp r ang1 ang2))
    (setq newarc (vlax-invoke space 'addarc newrp r ang2 ang1))
    )
  (vla-put-layer newarc (vla-get-layer tanobj))
  )
)
      (vla-endundomark doc)
      )
    )
  (princ)
  )

Thanks again!

LE

  • Guest
Re: Arc direction?
« Reply #6 on: May 30, 2006, 03:32:30 PM »
I need a small image/sample of the desired result.

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: Arc direction?
« Reply #7 on: May 30, 2006, 04:18:55 PM »
Here ya go Luis.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Arc direction?
« Reply #8 on: May 30, 2006, 05:07:57 PM »
I'm not sure how to check it, but maybe if you check the arc length after drawn in relationship to the distance between the pick point (from entsel) and the start point.  If it's to large, then swap the start angle, and end angle.

</thinking out loud>
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: Arc direction?
« Reply #9 on: May 30, 2006, 05:26:36 PM »
I'm not sure how to check it, but maybe if you check the arc length after drawn in relationship to the distance between the pick point (from entsel) and the start point.  If it's to large, then swap the start angle, and end angle.

</thinking out loud>
That's pretty much how I first solved it, Tim. I just added both arcs to the drawing and deleted the longest one. But I'm pretty sure there is a relatively simple way to calculate it (and I could have sworn I did this once before, in a time far, far away).

But then again, since I'm already creating objects to calculate things I could/should do with real math, I may as well just keep it that way.....

LE

  • Guest
Re: Arc direction?
« Reply #10 on: May 30, 2006, 06:18:47 PM »
Please test your routine, with something I included.

Code: [Select]
(defun 2area_t (a b c / a0 a1 b0 b1 c0 c1)
  (setq a0 (car a)
a1 (cadr a)
b0 (car b)
b1 (cadr b)
c0 (car c)
c1 (cadr c))
  (+
    (- (* a0 b1) (* a1 b0))
    (- (* a1 c0) (* a0 c1))
    (- (* b0 c1) (* c0 b1))))

(defun c:tst(/ *ACAD* ANG1 ANG2 CIRC DOC INTS NEWARC NEWEND NEWRP
   OFFOBJS P1 P2 PT R  SPACE TANEND TANENT TANOBJ TANSTART)
  (if (and (setq r (getdist "\nDesired Radius?: "))
   (setq pt (getpoint "\nPoint to start from: "))
   (setq tanent (entsel "\nLine or arc to be tangent to: "))
   )
    (progn
      (vl-load-com)
      (setq *acad* (vlax-get-acad-object)
    doc (vla-get-activedocument *acad*)
    space (if (= (getvar "cvport") 1)
    (vla-get-paperspace doc)
    (vla-get-modelspace doc)
    )
    )
      (vla-startundomark doc)
      (setq circ (vlax-invoke space 'addcircle pt r))
      (vla-put-visible circ :vlax-false)
      (setq tanobj (vlax-ename->vla-object (car tanent)))
      (setq offobjs (vlax-invoke tanobj 'offset r))
      (if (not (setq ints (vlax-invoke circ 'intersectwith (car offobjs) acExtendOtherEntity)))
(progn
  (vla-delete (car offobjs))
  (setq offobjs (vlax-invoke tanobj 'offset (- r)))
  (setq ints (vlax-invoke circ 'intersectwith (car offobjs) acExtendOtherEntity))
  )
)
      (vla-delete (car offobjs))
      (vla-delete circ)
      (if ints
(progn
  (if (= 3 (length ints))
    (setq newRP ints)
    (progn
      (setq p1 (list (car ints) (cadr ints) (caddr ints))
    p2 (cdddr ints))
      (if (< (distance p1 (cadr tanent)) (distance p2 (cadr tanent)))
(setq newrp p1)
(setq newrp p2)
)
      )
    )
  (setq newend (vlax-curve-getclosestpointto tanobj newrp t)
ang1 (angle newrp pt)
ang2 (angle newrp newend)
tanstart (vlax-get tanobj 'startpoint)
tanend (vlax-get tanobj 'endpoint)
)
  (if (< (distance tanstart newend) (distance tanend newend))
    (if (= (cdr (assoc 0 (entget (car tanent)))) "LINE")
      (vlax-put tanobj 'startpoint newend)
      (vla-put-startangle tanobj (angle (vlax-get tanobj 'center) newend))
      )
    (if (= (cdr (assoc 0 (entget (car tanent)))) "LINE")
      (vlax-put tanobj 'endpoint newend)
      (vla-put-endangle tanobj (angle (vlax-get tanobj 'center) newend))
      )
    )
  (if (< ang1 ang2)
    (setq newarc (vlax-invoke space 'addarc newrp r ang1 ang2))
    (setq newarc (vlax-invoke space 'addarc newrp r ang2 ang1))
    )
 
  (if (minusp (2area_t pt newend newrp))
    (progn
      (setq ptx pt pty newend)
      (vla-put-startangle newarc (angle newrp pty))
      (vla-put-endangle newarc (angle newrp ptx))))
 
  (vla-put-layer newarc (vla-get-layer tanobj))
  )
)
      (vla-endundomark doc)
      )
    )
  (princ)
  )

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Arc direction?
« Reply #11 on: May 30, 2006, 07:04:35 PM »
Luis, I was still having trouble with your solution when the line angle is around 315 deg.
This is when the start angle is sometimes less than the end angle.

Here is a solution using a function from D. C. Broad, Jr.
The only problem I had when using this on is if you pick the line to be tangent to past the point of tangency.
In this case the line should be trimmed from the other end.

Code: [Select]
(defun c:ptRtan (/ *ACAD* ANG1 ANG2 CIRC DOC INTS NEWARC NEWEND NEWRP
   OFFOBJS P1 P2 PT R SPACE TANEND TANENT TANOBJ TANSTART)
  (if (and (setq r (getdist "\nDesired Radius?: "))
   (setq pt (getpoint "\nPoint to start from: "))
   (setq tanent (entsel "\nLine or arc to be tangent to: "))
   )
    (progn
      (vl-load-com)
      (setq *acad* (vlax-get-acad-object)
    doc (vla-get-activedocument *acad*)
    space (if (= (getvar "cvport") 1)
    (vla-get-paperspace doc)
    (vla-get-modelspace doc)
    )
    )
      (vla-startundomark doc)
      (setq circ (vlax-invoke space 'addcircle pt r))
      (vla-put-visible circ :vlax-false)
      (setq tanobj (vlax-ename->vla-object (car tanent)))
      (setq offobjs (vlax-invoke tanobj 'offset r))
      (if (not (setq ints (vlax-invoke circ 'intersectwith (car offobjs) acExtendOtherEntity)))
(progn
  (vla-delete (car offobjs))
  (setq offobjs (vlax-invoke tanobj 'offset (- r)))
  (setq ints (vlax-invoke circ 'intersectwith (car offobjs) acExtendOtherEntity))
  )
)
      (vla-delete (car offobjs))
      (vla-delete circ)
      (if ints
(progn
  (if (= 3 (length ints))
    (setq newRP ints)
    (progn
      (setq p1 (list (car ints) (cadr ints) (caddr ints))
    p2 (cdddr ints))
      (if (< (distance p1 (cadr tanent)) (distance p2 (cadr tanent)))
(setq newrp p1)
(setq newrp p2)
)
      )
    )
  (setq newend (vlax-curve-getclosestpointto tanobj newrp t)
ang1 (angle newrp pt)
ang2 (angle newrp newend)
tanstart (vlax-get tanobj 'startpoint)
tanend (vlax-get tanobj 'endpoint)
)
  (if (< (distance tanstart newend) (distance tanend newend))
    (if (= (cdr (assoc 0 (entget (car tanent)))) "LINE")
      (vlax-put tanobj 'startpoint newend)
      (vla-put-startangle tanobj (angle (vlax-get tanobj 'center) newend))
      )
    (if (= (cdr (assoc 0 (entget (car tanent)))) "LINE")
      (vlax-put tanobj 'endpoint newend)
      (vla-put-endangle tanobj (angle (vlax-get tanobj 'center) newend))
      )
    )
  (if (minusp (SideOf (cadr tanent) newend newrp))
    (setq newarc (vlax-invoke space 'addarc newrp r ang1 ang2))
    (setq newarc (vlax-invoke space 'addarc newrp r ang2 ang1))
    )
  (vla-put-layer newarc (vla-get-layer tanobj))
  )
)
      (vla-endundomark doc)
      )
    )
  (princ)
  )

;;D. C. Broad, Jr.
;;(sideof <ray-origin> <another-point-on-ray> <point-to-be-tested>)
(defun SideOf (p1 p2 p / r)
  (setq r
   (cond
    ((equal p1 p 1e-10) 0)
    (t (sin (- (angle p1 p)(angle p1 p2))))))
  (if (equal r 0 1e-10) 0 r)
 )
;;return values
;;negative = point is to the right side of the ray
;;0 = point is on the ray
;;otherwise point is on the left side of the ray.
;;P1 should not equal P2 for meaningful results.
« Last Edit: May 30, 2006, 07:10:41 PM by CAB »
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

LE

  • Guest
Re: Arc direction?
« Reply #12 on: May 30, 2006, 07:14:29 PM »
Thanks CAB;

I did not ran many tests on the code.

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: Arc direction?
« Reply #13 on: May 30, 2006, 07:45:26 PM »
Yes, Luis, that appears to work quite well! I thank you very much.

Now if I can only recall how to figure out why this works.....I'm quickly realizing that things once learned don't always stay where you thought you'd stored them.....

CAB,
Thanks for posting Doug's (side-of) function...that's what I was looking for in my library and failed to find it. However, I was testing LE's version and it appeared to work in all of the cases I could think of. I've tried it all sorts of angles, from aither end of the line.....oh, my routine does think it is supposed to work with the end closest to the point selected when selecting the tangent object, maybe that makes a difference? Actually, I do see a problem when the radius is too large for the situation it gets placed at the other end of the line.....

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Arc direction?
« Reply #14 on: May 30, 2006, 08:54:34 PM »
Jeff & Luis,
What happens when you use the following example with the routine Luis provided?
PS line is 25 or so units long.
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.