Author Topic: ( C3D ) Points and Elevations - how to...?  (Read 18603 times)

0 Members and 1 Guest are viewing this topic.

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: ( C3D ) Points and Elevations - how to...?
« Reply #30 on: November 27, 2006, 08:01:30 PM »
I've reworked the code so the offsets at exterior angle points are placed correctly and I eliminated duplicate points being set on the interior angle offsets.

Yes, Sinc, I am actually crating an offset featureline since there are NO properties available via Activex it would be impossible to calculate any data along a curved section otherwise.

Code: [Select]
;|routine to demonstrate placing 'stakeout' points along a C3D FeatureLine.
  This has had limited testing and may cause instability issues due to
  the adding/removing of feature lines. Use at your own risk!
  Jeff Mishler - Nov. 2007 - written/tested in C3D2007-SP3
  additions to the code could include setting the descriptions to something meaningful.
  As it is, it just places a point at a specified offset and interval along a selected
  featureline. All vertices are included along the way.
  Version 2.0 measures along original featureline instead of the offset line
  and addresses angle points a bit better. Nov. 25, 2006
  Version 2.1 - minor tweaks to improve actions taken at angle points. Nov. 27, 2006
|;
(defun c:stakefeatures (/    *acad*     c3d c3ddoc
coords    dist       disttonextparam
ent    flatlist   interval offcoords
offdist    offpt      points secondpt
ss    startpt    thisparam tmpline
totaldist  *error*
       )
  (defun *error* (msg)
    (if msg
      (princ (strcat "\n....." msg))
    )
    (mapcar 'vlax-release-object (list points c3ddoc c3d))
    (princ)
  )
  ;;function to determine if vertice is angle point or curve start/end.
  (defun isAnglePt?
(obj idx / p1 p2 p3 dist1 dist1a dist2 dist2a angpt)
    (defun 2dpt (pt)
      (list (car pt) (cadr pt))
    )
    (setq p1 (2dpt (vlax-curve-getpointatparam obj (1- idx)))
  p2 (2dpt (vlax-curve-getpointatparam obj idx))
  p3 (2dpt (vlax-curve-getpointatparam obj (1+ idx)))
  dist1 (distance p1 p2)
  dist2 (distance p2 p3)
  dist1a (- (vlax-curve-getdistatparam obj idx)
    (vlax-curve-getdistatparam obj (1- idx))
)
  dist2a (- (vlax-curve-getdistatparam obj (1+ idx))
    (vlax-curve-getdistatparam obj idx)
)
    )
    (if (and (equal dist1 dist1a 0.0001)
     (equal dist2 dist2a 0.0001)
)
      (setq angpt t)
    )
    angpt
  )
  (setq *acad* (vlax-get-acad-object))
  (setq C3D (vla-getinterfaceobject
      *acad*
      "AeccXUiLand.AeccApplication.4.0"
    )
  )
  (setq C3Ddoc (vla-get-activedocument C3D))
  (setq points (vlax-get C3Ddoc 'points))
  (if (not *offdist*)
    (setq *offdist* 5.0)
  )
  (if (setq offdist
     (getdist
       (strcat
"\nOffset distance, use negative value for left offset?<"
(rtos *offdist*)
">: "
       )
     )
      )
    (setq *offdist* offdist)
  )
  (if (not *interval*)
    (setq *interval* 25.0)
  )
  (if (setq interval (getdist (strcat "\nStakeout interval?<"
      (rtos *interval*)
      ">: "
      )
     )
      )
    (setq *interval* interval)
  )
  ;;initiate selection loop...goes until nothing selected.
  (while (setq ss (ssget ":S:E" '((0 . "AECC_FEATURE_LINE"))))
    (setq ent (ssname ss 0))
    (setq startpt  (vlax-curve-getstartpoint ent)
  secondpt (vlax-curve-getpointatparam ent 1.0)
  offpt    (polar startpt
  (if (minusp *offdist*)
    (+ (angle startpt secondpt) (/ pi 2.0))
    (- (angle startpt secondpt) (/ pi 2.0))
  )
  (abs *offdist*)
   )
    )
    ;; must use the (command) to offset as there is no ActiveX method for this for featurelines
    (command "offset" (abs *offdist*) ent offpt "")
    (setq tmpline   (entlast)
  thisparam (vlax-curve-getstartparam ent)
  coords    (list (vlax-curve-getclosestpointto
    tmpline
    (vlax-curve-getpointatparam ent thisparam)))
  totaldist 0.0
    )
    (while (< thisparam (vlax-curve-getendparam ent))
      (setq disttonextparam
     (vlax-curve-getdistatparam
       ent
       (1+ thisparam)
     )
      )
      (if (< (vlax-curve-getdistatparam ent thisparam) totaldist)
(setq
  coords (cons (vlax-curve-getclosestpointto
tmpline
(vlax-curve-getpointatdist ent totaldist)

       )
       coords
)
)
      )
      (while (< (setq totaldist (+ totaldist *interval*))
disttonextparam
     )
(setq
  coords (cons (vlax-curve-getclosestpointto
tmpline
(vlax-curve-getpointatdist ent totaldist)

       )
       coords
)
)
      )
      (setq thisparam (1+ thisparam))
      (if (and (< thisparam (vlax-curve-getendparam ent))
       (isAnglePt? ent thisparam)
  )
(progn
  (setq dist (vlax-curve-getdistatparam ent thisparam)
tmp1 (vlax-curve-getpointatdist ent (- dist 0.01))

tmp2 (vlax-curve-getclosestpointto tmpline tmp1)
  )
  (if (equal (vlax-curve-getdistatparam tmpline thisparam)
     (vlax-curve-getdistatpoint tmpline tmp2)
     0.001
      )
    (setq coords (cons tmp2 coords))
    (progn
      (setq tmp2   (vlax-curve-getpointatdist
     tmpline
     (+ (vlax-curve-getdistatpoint tmpline tmp2) 0.01)
   )
    coords (cons tmp2 coords)
      )
      (setq tmp1   (vlax-curve-getpointatdist ent (+ dist 0.01))

    tmp2   (vlax-curve-getclosestpointto tmpline tmp1)
    tmp2   (vlax-curve-getpointatdist
     tmpline
     (- (vlax-curve-getdistatpoint tmpline tmp2) 0.01)
   )
    coords (cons tmp2 coords)
      )
    )
  )
)
(setq
  coords (cons (vlax-curve-getclosestpointto
tmpline
(vlax-curve-getpointatparam ent thisparam)

       )
       coords
)
)

      )
    )
    (entdel tmpline)
    (setq flatlist (apply 'append (reverse coords)))
    (vlax-invoke
      points
      'addmultiple
      (length coords)
      flatlist
      'added
    )
  )
  (*error* "Finished!")
  (princ)
)
While it would be possible to incorporate other items, I think that, for now, letting the user manually set a correct site, current point number, point group, etc. prior to running the program is the way to go.......

sinc

  • Guest
Re: ( C3D ) Points and Elevations - how to...?
« Reply #31 on: November 27, 2006, 08:33:14 PM »
I've reworked the code so the offsets at exterior angle points are placed correctly and I eliminated duplicate points being set on the interior angle offsets.

Yes, Sinc, I am actually crating an offset featureline since there are NO properties available via Activex it would be impossible to calculate any data along a curved section otherwise.

I haven't had time to work with it yet, so I'm not entirely sure what you're doing.  Are you just getting a 3D point along the feature line?

Have you tried using the First Derivative?  If it works, then I think you should be able to use routines like the following to calculate an offset at any point:
Code: [Select]
  (setq *VLutil:quad*    (/ PI 2)) ; radians in a quadrant

  (defun VLutil:azimuthAtParam (entity selPar / dvec)
    (setq dvec (vlax-curve-getFirstDeriv entity selPar))
    (angle '(0 0) dvec)
    ;; note: angle projected on xy plane
  ) ;defun VLutil:azimuthAtParam


 ; value of dir: 1 = clockwise (right) -1 = counterclockwise (left)
  (defun VLutil:offsetAtPoint (entity point dir offDist)
    (if (= offDist 0)
      point
      (polar
point
(- (VLutil:azimuthAtParam
     entity
     (vlax-curve-getParamAtPoint entity point)
   ) ;_ VLutil:azimuthAtParam
   (* dir *VLutil:quad*)
) ;_ +
offDist
      ) ;_ polar
    ) ;if
  ) ;defun VLutil:offsetAtPoint


  (defun VLutil:offsetAtParam (entity param dir offDist)
    (if (= offDist 0)
      (vlax-curve-getPointAtParam entity param)
      (polar
(vlax-curve-getPointAtParam entity param)
(- (VLutil:azimuthAtParam entity param) (* dir *VLutil:quad*))
offDist
      ) ;_ polar
    ) ;if
  ) ;_ defun

This came from my standard utility library.  There are two routines in there - one to calculate an offset point at a given Param along the entity, and one to calculate an offset at at a point along the entity.  The azimuthAtParam routine is a utility routine used by both of the others.

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: ( C3D ) Points and Elevations - how to...?
« Reply #32 on: November 28, 2006, 11:39:41 AM »
I've never used the FirstDerivitive or SecondDerivitive, mainly because I don't have a clue what they represent.....

Essentially, yes, I am getting 3d points along the featureline then casting them to the offset featureline (getclosestpointto). Where there is an external angle I use 2 points, 0.01 units in each direction from the actual angle point, find the corresponding point on the offset line, then move those points back the 0.01 units to be exactly offset from the angle point. On Interior angles, the closestpointto always returns the offset angle point.

HTH

sinc

  • Guest
Re: ( C3D ) Points and Elevations - how to...?
« Reply #33 on: November 28, 2006, 11:54:02 AM »
I've never used the FirstDerivitive or SecondDerivitive, mainly because I don't have a clue what they represent.....

Oh, OK, try the little library routines I posted, then.

First Derivative is essentially the direction vector of the object at the specified point (or of a tangent at the point, if the point is in a curve).  So by adding or subtracting 90° (PI/2 radians), you can get the direction vector for an offset.  The direction of the entity is the direction of increasing parameter numbers.

The routines I posted simply take an object, a point/param, a direction (clockwise or counterclockwise), and an offset distance.  Then they return the coordinates of the offset.  You may or may not have to deal with the elevation separately - I haven't tried running the routines on 3D linework.  But they might return a point with the correct elevation as they are.  If not, a minor tweak might correct that issue.

Net result is that, by using those little library routines, you should be able to eliminate the need for creating the offset.

Second Derivative is basically the "rate of change".  A line ALWAYS has a second derivative of 0.  I think clockwise arcs have second derivatives less-than zero, and counterclockwise is greater than zero (or maybe it was the other way around).  The absolute value of the second deriv is bigger for sharper curves.  It probably isn't useful in this particular situation, but it is very useful in other situations.

When I get a chance, I'll start playing with it.  But right now, I'm still stuck setting up Styles so we can get our pilot project done...   :-P

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: ( C3D ) Points and Elevations - how to...?
« Reply #34 on: November 28, 2006, 02:47:31 PM »
OK, thanks for the quick lesson on derivitives! Based on this information and using revised versions of your functions I've come up with a routine that does the best job, yet, of staking the offsets. And now there's no worry of corrupting sites due to offsetting featurelines!

The only thing left, if it's really required, would be to set the descriptions of the points. However, to do so would mean setting the points one at a time and setting the description immediately after creation...the 'AddMultiple method of the Points object will no longer be able to be used. It may slow it down a bit.
Code: [Select]
;|routine to demonstrate placing 'stakeout' points along a C3D FeatureLine.
  This has had limited testing and may cause instability issues due to
  the adding/removing of feature lines. Use at your own risk!
  Jeff Mishler - Nov. 2007 - written/tested in C3D2007-SP3
  additions to the code could include setting the descriptions to something meaningful.
  As it is, it just places a point at a specified offset and interval along a selected
  featureline. All vertices are included along the way.
  Version 2.0 measures along original featureline instead of the offset line
  and addresses angle points a bit better. Nov. 25, 2006
  Version 2.1 - minor tweaks to improve actions taken at angle points. Nov. 27, 2006
  Version 3.0 - removed code to offset featureline, replaced with code to calculate
    the offset points direct (thanks to Sinc for the functions to do this)
|;
(defun c:stakefeatures (/   *acad*    ang1      ang2
c3d   c3ddoc    coords    disttonextparam
ent   entity    flatlist  interval
off1   off2     offdist   points
pt1   ss     thisparam tmp1
tmp2   tmp3     totaldist *error*
       )
  (defun *error* (msg)
    (if msg
      (princ (strcat "\n....." msg))
    )
    (mapcar 'vlax-release-object (list points c3ddoc c3d))
    (princ)
  )
  ;;function to determine if vertice is angle point or curve start/end.
  (defun isAnglePt?
(obj idx / p1 p2 p3 dist1 dist1a dist2 dist2a angpt)
    (defun 2dpt (pt)
      (list (car pt) (cadr pt))
    )
    (setq p1 (2dpt (vlax-curve-getpointatparam obj (1- idx)))
  p2 (2dpt (vlax-curve-getpointatparam obj idx))
  p3 (2dpt (vlax-curve-getpointatparam obj (1+ idx)))
  dist1 (distance p1 p2)
  dist2 (distance p2 p3)
  dist1a (- (vlax-curve-getdistatparam obj idx)
    (vlax-curve-getdistatparam obj (1- idx))
)
  dist2a (- (vlax-curve-getdistatparam obj (1+ idx))
    (vlax-curve-getdistatparam obj idx)
)
    )
    (if (and (equal dist1 dist1a 0.0001)
     (equal dist2 dist2a 0.0001)
)
      (setq angpt t)
    )
    angpt
  )
;;;; 
  (defun VLutil:azimuthAtParam (entity selPar / dvec)
    (setq dvec (vlax-curve-getFirstDeriv entity selPar))
    (angle '(0 0) dvec)
    ;; note: angle projected on xy plane
  ) ;defun VLutil:azimuthAtParam
;;;;
  (defun VLutil:offsetAtParam (entity param offDist)
    (if (= offDist 0)
      (vlax-curve-getPointAtParam entity param)
      (polar
(vlax-curve-getPointAtParam entity param)
(- (VLutil:azimuthAtParam entity param) (/ pi 2.0))
offDist
      ) ;_ polar
    ) ;if
  ) ;_ defun
  (defun VLutil:offsetAtPoint (entity point offDist)
    (if (= offDist 0)
      point
      (polar
point
(- (VLutil:azimuthAtParam
     entity
     (vlax-curve-getParamAtPoint entity point)
   ) ;_ VLutil:azimuthAtParam
   (/ pi 2.0)
) ;_ +
offDist
      ) ;_ polar
    ) ;if
  ) ;defun VLutil:offsetAtPoint
;;;;;;;;
  (setq *acad* (vlax-get-acad-object))
  (setq C3D (vla-getinterfaceobject
      *acad*
      "AeccXUiLand.AeccApplication.4.0"
    )
  )
  (setq C3Ddoc (vla-get-activedocument C3D))
  (setq points (vlax-get C3Ddoc 'points))
  (if (not *offdist*)
    (setq *offdist* 5.0)
  )
  (if (setq offdist
     (getdist
       (strcat
"\nOffset distance, use negative value for left offset?<"
(rtos *offdist*)
">: "
       )
     )
      )
    (setq *offdist* offdist)
  )
  (if (not *interval*)
    (setq *interval* 25.0)
  )
  (if (setq interval (getdist (strcat "\nStakeout interval?<"
      (rtos *interval*)
      ">: "
      )
     )
      )
    (setq *interval* interval)
  )
  ;;initiate selection loop...goes until nothing selected.
  (while (setq ss (ssget ":S:E" '((0 . "AECC_FEATURE_LINE"))))
    (setq ent (ssname ss 0))
    (setq thisparam (vlax-curve-getstartparam ent)
  coords    (list (VLutil:offsetAtParam ent thisparam *offdist*))
  totaldist 0.0
    )
    (while (< thisparam (vlax-curve-getendparam ent))
      (setq disttonextparam
     (vlax-curve-getdistatparam
       ent
       (1+ thisparam)
     )
      )
      (if (< (vlax-curve-getdistatparam ent thisparam) totaldist)
(setq
  coords (cons (VLutil:offsetAtPoint
ent
(vlax-curve-getpointatdist ent totaldist)
*offdist*
       )
       coords
)
)
      )
      ;;;set points at the desired interval along the segment
      (while (< (setq totaldist (+ totaldist *interval*))
disttonextparam
     )
(setq
  coords (cons (VLutil:offsetAtPoint
ent
(vlax-curve-getpointatdist ent totaldist)
*offdist*
       )
       coords
)
)
      )
      (setq thisparam (1+ thisparam))
      ;;we're at the next param, is
      (if (and (< thisparam (vlax-curve-getendparam ent))
       (isAnglePt? ent thisparam)
  )
(progn
  ;;;it's an angle point, now see if it's an internal or external angle
  (setq pt1  (vlax-curve-getpointatparam ent thisparam)
ang1 (VLutil:azimuthAtParam ent (- thisparam 0.01));;;get azimuth back
ang2 (VLutil:azimuthAtParam ent (+ thisparam 0.01));;;get azimuth ahead
off1 (polar pt1 (- ang1 (/ pi 2.0)) *offdist*)
off2 (polar pt1 (- ang2 (/ pi 2.0)) *offdist*)
tmp1 (polar off1 ang1 20)
tmp2 (polar off2 ang2 -20)
tmp3 (inters off1 tmp1 off2 tmp2 nil);;calc intersection point of offsets
  )
  (if (not (equal ang1 (angle off1 tmp3) 0.001))
    ;;it's an internal, return the point of intersection
    (setq coords (cons tmp3 coords))
    (progn
      ;;;it's an external, use both offset points
      (setq coords (cons off1 coords)
    coords (cons off2 coords)
      )
    )
  )
)
(setq
  coords (cons (VLutil:offsetAtParam ent thisparam *offdist*)
       coords
)
)

      )
    )
    (setq flatlist (apply 'append (reverse coords)))
    (vlax-invoke
      points
      'addmultiple
      (length coords)
      flatlist
      'added
    )
  )
  (*error* "Finished!")
  (princ)
)
« Last Edit: November 28, 2006, 02:48:42 PM by Jeff_M »

sinc

  • Guest
Re: ( C3D ) Points and Elevations - how to...?
« Reply #35 on: November 28, 2006, 06:14:17 PM »
Cool!

I may expand what you've done, when I get a chance.  One thing that I want is the ability to automatically set the radius point of smaller-radius curves, and give the radius points a description like "4.5 RP" for 4.5-foot radius, or "3 RP" for 3-foot, etc.  If the radius is bigger than a user-specified value, then no radius point should be set.

If you're interested, you can try and do it yourself.  I'm attaching my VLutil.LSP library.  It has the routines I posted earlier, plus more.  They can be pretty useful.  For example, there's a MarkPoint routine which draws a temporary X on the screen at the specified point (the X goes away when the user PANs or ZOOMs the screen).  This is useful in lots of routines, for indicating a spot to the user without adding any elements to the drawing.

The key routine for setting a Radius Point of a polyline is the VLUtil:rpOfSegment routine, near the end.  It uses the Second Derivative and the Bulge to set the radius point.

Once I looked at it, I remembered that I steered you a bit wrong.  You can't determine which side of the polyline by using Second Derivative, but the magnitude of the Second Derivative is the same as the radius point of the curve.  (This gets a bit funky with splines, and may not work as expected, since Splines do not have a consistent radius point).  Instead, use the Buldge to determine which side the radius point is on.  Then (ABS Second Deriv) is the same as the length of the radius.  In other words, I use 2nd deriv to get the radius, 1st deriv to get the tangent bearing, and Buldge to figure out which side of the polyline I want to be on.  That lets me calculate the Radius Point.

(I also have a similar library of utility commands for Land Desktop.  It's available in that SincPac thing I posted in another thread.)

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: ( C3D ) Points and Elevations - how to...?
« Reply #36 on: November 28, 2006, 06:38:59 PM »
Thanks for the VLutil.lsp! I'm sure it will come in handy even though I'm trying to steer away from lisp. I have an "Xmarksthespot.lsp" that I wrote quite some time ago for use in a pline editting function. :-P

As for calc'ing the radius of these feature lines....I wish you luck! These things don't have Bulges so I think that comparing adjacent firstderiv's may need to be used (but now I'm talking over my head so it's more of a best guess effort here). But feel free to do with it as you please, even if it's only a starting point for what you need.

For me, I learned quite a bit about those 2 (vlax-curve-) functions as well as what the C3D programmers decided waht we didn't need to mucking around with....ie: they seem to think that we will damage the database if they allowed us access to the featurelines. (Good possibility since those are some of the items that CAN destroy your drawing, if not handled correctly....sounds like I'm talking about nitro-glycerin here :-/)

I have, and use, your functions you previously posted - SincPac. Quite nice to not have to roll my own for everything! Thanks for those, too!

sinc

  • Guest
Re: ( C3D ) Points and Elevations - how to...?
« Reply #37 on: November 28, 2006, 09:11:03 PM »
I have, and use, your functions you previously posted - SincPac. Quite nice to not have to roll my own for everything! Thanks for those, too!

Yeah, some of those have really cut our calc times.  The XGRD, PT2ALIGN, and PT2SURF commands in particular have become real workhorses for us in Land Desktop.

I sent a feature request to Autodesk.  I actually asked for a full-fledged "Stakeout Object".  This object could be linked to a whole series of Feature Lines, and options like "Offset Distance", "Maximum Gap Distance", "Set Radius Points", etc. could all be set in the Stakeout Object.  The parameters in the Stakeout Object could be overridden for specific feature lines, for example, if one line need 4-foot offsets instead of 3-foot offsets for some reason.

Then if the feature lines change, the Offset Points also change.  If the user changes the Maximum Gap Distance, the points are recalc'd.  If the user adds a grade break to a feature line, the points are recalc'd, and a point is added at the new grade break.  The points in a feature set auto-renumber, so that they stay in a coherent staking order for field guys.  And any other features that come up.

We'll see how they respond...   :lol:

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: ( C3D ) Points and Elevations - how to...?
« Reply #38 on: November 28, 2006, 11:50:44 PM »
.....  I actually asked for a full-fledged "Stakeout Object".  .....
We'll see how they respond...   :lol:
Now THAT would be too slick! Great ideas, who'd you send these to? Might I suggest you also send this request to Nick Zeeben? He's a programmer recently hired  to be on the C3D team...I think he has somewhat of a survey background as well. nick.zeeben At Auodesk dot youknow

Here's hoping they respond kindly!

sinc

  • Guest
Re: ( C3D ) Points and Elevations - how to...?
« Reply #39 on: February 21, 2007, 10:49:39 PM »
Hard to believe it's been nearly three months, and I'm finally getting to construction calcs.  That's what winter in Colorado can do...   ^-^

But construction calcs are becoming a hot item again.  I finally got a chance to start digging through this.  I seemed to find some errors in the code.  1) totaldist seemed to be calculated incorrectly and 2) the routine would blow up if two segments were tangent, such as when there's a grade break in a long straight section.  I fixed those.  Also, to make the code a bit more readable, I changed "totaldist" to "currentdist", and "disttonextparam" to "distatnextparam".  And I went ahead and made the angle-point check a little tighter (param±.0001 instead of ±.01 to get azimuth forward and azimuth back).  It's very likely that the .01 is safe in all real-world situations, but .0001 made me feel better.  And I added Undo marks.

I think it's all working now.  We're slowly getting this beast whipped into shape...    8-)

Code: [Select]
;|routine to demonstrate placing 'stakeout' points along a C3D FeatureLine.
  This has had limited testing and may cause instability issues due to
  the adding/removing of feature lines. Use at your own risk!
  Jeff Mishler - Nov. 2007 - written/tested in C3D2007-SP3
  additions to the code could include setting the descriptions to something meaningful.
  As it is, it just places a point at a specified offset and interval along a selected
  featureline. All vertices are included along the way.
  Version 2.0 measures along original featureline instead of the offset line
  and addresses angle points a bit better. Nov. 25, 2006
  Version 2.1 - minor tweaks to improve actions taken at angle points. Nov. 27, 2006
  Version 3.0 - removed code to offset featureline, replaced with code to calculate
    the offset points direct (thanks to Sinc for the functions to do this)
  Version 3.1 - bug fixes, add undo marks Feb 21, 2007 (by Sinc)
|;
(defun c:stakefeatures (/   *acad*    ang1      ang2
c3d   c3ddoc    coords    distatnextparam
ent   entity    flatlist  interval
off1   off2     offdist   points
pt1   ss     thisparam tmp1
tmp2   tmp3     currentdist *error*
                        usrcmd
       )
  (setq usrcmd (getvar "cmdecho"))
  (setvar "cmdecho" 0)
  (defun *error* (msg)
    (if msg
      (princ (strcat "\n....." msg))
    )
    (mapcar 'vlax-release-object (list points c3ddoc c3d))
    (princ)
  )
  ;;function to determine if vertice is angle point or curve start/end.
  (defun isAnglePt?
(obj idx / p1 p2 p3 dist1 dist1a dist2 dist2a angpt)
    (defun 2dpt (pt)
      (list (car pt) (cadr pt))
    )
    (setq p1 (2dpt (vlax-curve-getpointatparam obj (1- idx)))
  p2 (2dpt (vlax-curve-getpointatparam obj idx))
  p3 (2dpt (vlax-curve-getpointatparam obj (1+ idx)))
  dist1 (distance p1 p2)
  dist2 (distance p2 p3)
  dist1a (- (vlax-curve-getdistatparam obj idx)
    (vlax-curve-getdistatparam obj (1- idx))
)
  dist2a (- (vlax-curve-getdistatparam obj (1+ idx))
    (vlax-curve-getdistatparam obj idx)
)
    )
    (if (and (equal dist1 dist1a 0.0001)
     (equal dist2 dist2a 0.0001)
)
      (setq angpt t)
    )
    angpt
  )
;;;; 
  (defun VLutil:azimuthAtParam (entity selPar / dvec)
    (setq dvec (vlax-curve-getFirstDeriv entity selPar))
    (angle '(0 0) dvec)
    ;; note: angle projected on xy plane
  ) ;defun VLutil:azimuthAtParam
;;;;
  (defun VLutil:offsetAtParam (entity param offDist)
    (if (= offDist 0)
      (vlax-curve-getPointAtParam entity param)
      (polar
(vlax-curve-getPointAtParam entity param)
(- (VLutil:azimuthAtParam entity param) (/ pi 2.0))
offDist
      ) ;_ polar
    ) ;if
  ) ;_ defun
  (defun VLutil:offsetAtPoint (entity point offDist)
    (if (= offDist 0)
      point
      (polar
point
(- (VLutil:azimuthAtParam
     entity
     (vlax-curve-getParamAtPoint entity point)
   ) ;_ VLutil:azimuthAtParam
   (/ pi 2.0)
) ;_ +
offDist
      ) ;_ polar
    ) ;if
  ) ;defun VLutil:offsetAtPoint
;;;;;;;;
  (setq *acad* (vlax-get-acad-object))
  (setq C3D (vla-getinterfaceobject
      *acad*
      "AeccXUiLand.AeccApplication.4.0"
    )
  )
  (setq C3Ddoc (vla-get-activedocument C3D))
  (setq points (vlax-get C3Ddoc 'points))
  (if (not *offdist*)
    (setq *offdist* 5.0)
  )
  (if (setq offdist
     (getdist
       (strcat
"\nOffset distance, use negative value for left offset?<"
(rtos *offdist*)
">: "
       )
     )
      )
    (setq *offdist* offdist)
  )
  (if (not *interval*)
    (setq *interval* 25.0)
  )
  (if (setq interval (getdist (strcat "\nStakeout interval?<"
      (rtos *interval*)
      ">: "
      )
     )
      )
    (setq *interval* interval)
  )
  ;;initiate selection loop...goes until nothing selected.
  (command "._undo" "_begin")
  (while (setq ss (ssget ":S:E" '((0 . "AECC_FEATURE_LINE"))))
    (setq ent (ssname ss 0))
    (setq thisparam (vlax-curve-getstartparam ent)
  coords    (list (VLutil:offsetAtParam ent thisparam *offdist*))
    )
    (while (< thisparam (vlax-curve-getendparam ent))
      (setq currentdist
     (vlax-curve-getdistatparam
       ent
       thisparam
     )
            distatnextparam
     (vlax-curve-getdistatparam
       ent
       (1+ thisparam)
     )
      )
      ;;;set points at the desired interval along the segment
      (while (< (setq currentdist (+ currentdist *interval*))
distatnextparam
     )
(setq
  coords (cons (VLutil:offsetAtPoint
ent
(vlax-curve-getpointatdist ent currentdist)
*offdist*
       )
       coords
)
)
      )
      (setq thisparam (1+ thisparam))
      ;;we're at the next param, is
      (if (and (< thisparam (vlax-curve-getendparam ent))
       (isAnglePt? ent thisparam)
  )
(progn
  ;;;it's an angle point, now see if it's an internal or external angle
  (setq pt1  (vlax-curve-getpointatparam ent thisparam)
ang1 (VLutil:azimuthAtParam ent (- thisparam 0.0001));;;get azimuth back
ang2 (VLutil:azimuthAtParam ent (+ thisparam 0.0001));;;get azimuth ahead
off1 (polar pt1 (- ang1 (/ pi 2.0)) *offdist*)
off2 (polar pt1 (- ang2 (/ pi 2.0)) *offdist*)
tmp1 (polar off1 ang1 20)
tmp2 (polar off2 ang2 -20)
tmp3 (inters off1 tmp1 off2 tmp2 nil);;calc intersection point of offsets
  )
          (if (null tmp3)
            ;;could not get intersect; must be tangent segments, return one point
            (setq coords (cons off1 coords))
            (if (not (equal ang1 (angle off1 tmp3) 0.001))
              ;;it's an internal, return the point of intersection
              (setq coords (cons tmp3 coords))
              ;;;it's an external, use both offset points
              (setq coords (cons off1 coords)
                    coords (cons off2 coords)
              )
            )
          )
)
(setq
  coords (cons (VLutil:offsetAtParam ent thisparam *offdist*)
       coords
)
)

      )
    )
    (setq flatlist (apply 'append (reverse coords)))
    (vlax-invoke
      points
      'addmultiple
      (length coords)
      flatlist
      'added
    )
  )
  (command "._undo" "_end")
  (*error* "Finished!")
  (setvar "cmdecho" usrcmd)
  (princ)
)
« Last Edit: February 21, 2007, 10:56:48 PM by sinc »

sinc

  • Guest
Re: ( C3D ) Points and Elevations - how to...?
« Reply #40 on: February 22, 2007, 12:15:25 AM »
Oh, wait, I think I understand what you were doing with the totaldist thing.  You were setting points on every even station, so a 25' spacing would have a stake at 0+25, 0+50, 0+75, etc.  Sof there's a PC at Sta 0+30, there's still a Cogo point at Sta 0+50.  The way I changed it, it now restarts measuring for every segment.  So if there's a PC at Sta 0+30, the next point is now 0+55 (25' from the PC).

I beleive the crash I was experiencing was caused by the fact that the last segment was shorter than the station interval.  Basically, there was an angle point between the last even 25' station and the end of the feature line.  That caused an unexpected nil value to jump in there.

I think I'll play with this a bit, and see if I can make it a bit more flexible.  Unfortunately, after working a bit in C#, I'm not exactly jumping in joy to be working in Lisp...   :wink:

Hopefully Autodesk has exposed more of the API in 2008, the feature line stuff in particular.
« Last Edit: February 22, 2007, 12:20:01 AM by sinc »

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: ( C3D ) Points and Elevations - how to...?
« Reply #41 on: February 22, 2007, 11:15:41 AM »
Yes, you are correct about how I used the stationing. I wasn't sure how these items are normally calc'ed/staked so I just used that method.

For the Lisp vs C#....I had started converting this to C# but had to give it up in favor of Real Work. I did get most of the Lisp functions you provided converted and was working on setting the points when I got pulled away. If you'd like that code, I'd be more than willing to share it....although my variable & function naming may not be too great (that's one area I seem to lack a knack for).

Keep wishing for the 2008 API....it ain't there. The only access to FeatureLines are to Corridor FeatureLines, which is pretty much what 2007 offered us.

sinc

  • Guest
Re: ( C3D ) Points and Elevations - how to...?
« Reply #42 on: February 22, 2007, 01:20:05 PM »
Which functions did you convert?  That might be useful.

I was thinking of doing the same thing, but the big problem I see is that, without the Feature Lines API, the only way we have to work with these things is through the vlax-curve functions.  Did you figure out how to call those from C#?  I wasn't sure how to accomplish that.

And just for info, I notice that the vlax-curve-secondDeriv function is broken for feature lines.  vlax-curve-firstDeriv works, but the second deriv always returns 0.  I suspect Autodesk did something really funky with these things.  The only way the second deriv should return (0,0,0) is when the segment is a line, so at it's heart, the feature line might really be broken into line segments, just like what you get if you try to explode a feature line with curves in it.  The curve part seems to be some sort of "overlay".

This is really frustrating.  Autodesk doesn't provide us with all the functionality we need, and they also fail to provide API support so we can write it ourselves.  But I suppose that just makes it more satisfying when we actually manage to hack through the problems and get something working the way we want it...  It just takes a lot of brain-damage.   :laugh:

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: ( C3D ) Points and Elevations - how to...?
« Reply #43 on: February 22, 2007, 02:40:10 PM »
The Curve functions are exposed in the .NET environment...no need to try to use the lisp functions. Yes, it was the helper functions for obtaining the points along the Feature lines that I worked on. I'm attaching my Class1.cs file from my VS2005 project. I think SharpDevelop can read this....if not just open in Notepad and copy it from there. Feel free to use what you can. This is the project that I had posted to the Adesk group about the multiple warnings coming up. It is in no way a finished, or even close to, project but it should give you some ideas (more on how not to code, probably, as this was my first major venture into the land of C#)

sinc

  • Guest
Re: ( C3D ) Points and Elevations - how to...?
« Reply #44 on: February 25, 2007, 11:20:16 PM »
Here's what I have now.

I finally realized that the SecondDerivative works when the feature line is in a 2D plane, but not when it's in 3D.  That means it can't be used.  Working without the bulge or the SecondDerivative makes things more difficult, but I found a way of using geometry to work around the problem.

This version sets points at equal intervals between angle points and grade breaks.  It also sets radius points and point descriptions, and remembers its settings.  I also broke up the code, and got a couple of basic utility libraries started.  The libraries are probably bound to change a fair bit moving forward, though, since I just started with C# and .NET last weekend, and I'm still figuring out the language.  But it should be a decent start.

There's also a compiled DLL in the zip package if anyone wants to try it without compiling the code.  You should be able to just NETLOAD the DLL into Civil-3D, and type STAKEFEATURES to run it.
« Last Edit: February 25, 2007, 11:24:08 PM by sinc »