Author Topic: ( C3D ) Create Setbacks and Lot Easements from Parcels  (Read 3093 times)

0 Members and 1 Guest are viewing this topic.

sinc

  • Guest
( C3D ) Create Setbacks and Lot Easements from Parcels
« on: April 07, 2007, 06:00:54 PM »
Many of us have probably hit some sort of situation where we have to add setbacks or easements to all the lots in a subdivision.  These are typically at varying distances around the lot - around here, a common one is 7' on the front, 5' on the sides, and 10' on the rear.  These are often a pain to draw.

Here's a routine that simplifies the process.  The "interesting part" is attached to this post, but the complete source code, along with a DLL compiled for C3D2007 and instructions (with screen shots), are available on our web site.

Code: [Select]
private void processParcel(Curve parcel)
{
double paramCount = parcel.EndParam;
double startFront = selectParam(parcel, "\nSelect start of lot front");
if (startFront.Equals(-1)) return;
double endFront = selectParam(parcel, "\nSelect end of lot front");
if (endFront.Equals(-1)) return;
double startRear=-1, endRear=-1;
if (settings.CreateRear) {
startRear = selectParam(parcel, "\nSelect start of lot back");
if (startRear.Equals(-1)) return;
endRear = selectParam(parcel, "\nSelect end of lot back");
if (endRear.Equals(-1)) return;
}
Curve2dCollection calcs = new Curve2dCollection();
double curParam = startFront;
double offDist=0;
for (int i=0; i<paramCount; i++) {
if (settings.CreateRear && (curParam == startRear))
offDist = settings.RearOffset;
else if ((curParam == endFront) || (settings.CreateRear && (curParam == endRear)))
offDist = settings.SideOffset;
if (i==0) offDist = settings.FrontOffset;
Curve2d c = CurveUtil.GetCurve2dOffsetForSegment(parcel, curParam, offDist);
calcs.Add(c);
curParam++;
if (curParam == paramCount) curParam=0;
}

// prune unwanted vertices from "calc" segments by combining segments
int curSeg=0, nextSeg=1;
Curve2dCollection merged = new Curve2dCollection();
while (curSeg < paramCount) {
Curve2d baseSeg = (Curve2d)calcs[curSeg].Clone();
bool mergedSegments = true;
while (mergedSegments && (nextSeg < paramCount)) {
mergedSegments = false;
Curve2d addSeg = calcs[nextSeg];
if (baseSeg.GetType().Equals(addSeg.GetType())) {
if (baseSeg is LinearEntity2d) {
LinearEntity2d bseg = (LinearEntity2d)baseSeg;
if (bseg.IsColinearTo((LinearEntity2d)addSeg)) {
baseSeg = new LineSegment2d(bseg.StartPoint,((LineSegment2d)addSeg).EndPoint);
nextSeg++;
mergedSegments = true;
}
}
else {
CircularArc2d bseg = (CircularArc2d)baseSeg;
if (bseg.Center.GetDistanceTo(((CircularArc2d)addSeg).Center) < .00001) {
baseSeg = new CircularArc2d(bseg.StartPoint, bseg.EndPoint, ((CircularArc2d)addSeg).EndPoint);
nextSeg++;
mergedSegments = true;
}
}
}
}
merged.Add(baseSeg);
curSeg = nextSeg++;
}

// create database entities from "merged" segments
Database db = ACAD.DocumentManager.MdiActiveDocument.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
paramCount = merged.Count;
for (int i=0; i<paramCount; i++) {
int bck = i-1;
int fwd = i+1;
if (bck < 0) bck=(int)paramCount-1;
if (fwd==paramCount) fwd=0;
Point2d x = findIntersection(merged[bck], merged[i]);
Point2d y = findIntersection(merged[i], merged[fwd]);
Point3d x3d = new Point3d(x.X, x.Y, 0);
Point3d y3d = new Point3d(y.X, y.Y, 0);
Entity segment;
if (merged[i] is CircularArc2d) {
CircularArc2d a = (CircularArc2d)merged[i];
Point2d rp = a.Center;
double startAng = rp.GetVectorTo(x).Angle;
double endAng = rp.GetVectorTo(y).Angle;
if (a.IsClockWise) {
double tmp = startAng;
startAng = endAng;
endAng = tmp;
}
segment = new Arc(new Point3d(rp.X,rp.Y,0), a.Radius, startAng, endAng);
}
else {
segment = new Line(x3d,y3d);
}
segment.Layer = settings.LayerName;
curSpace.AppendEntity(segment);
tr.AddNewlyCreatedDBObject(segment, true);
}
tr.Commit();
}
}

// this routine will always return a value.  If it can't find an
// intersection point, it simply returns the start point of c2.
private Point2d findIntersection(Curve2d c1, Curve2d c2)
{
Point2d referencePoint = c2.StartPoint;

// If offset line endpoints are touching (ie within .0001), just return
// one of the values.  This takes care of the case where a line segment
// hits a tangent curve.
if (c1.EndPoint.GetDistanceTo(referencePoint)<0.0001)
return referencePoint;
// Check to see if offset lines intersect
CurveCurveIntersector2d intx = new CurveCurveIntersector2d(c1, c2);
if (intx.NumberOfIntersectionPoints==0) {
//  Offset segments don't intersect, extend them
if (c1 is LineSegment2d) c1=((LineSegment2d)c1).GetLine();
if (c2 is LineSegment2d) c2=((LineSegment2d)c2).GetLine();
// CircularArc2d entities are not defined like arcs; instead, they are
// defined using angles from a reference vector.
// So the easiest way to extend them is to turn them into full circles and
// then analyze both intersect points to return the appropriate one.
if (c1 is CircularArc2d) {
((CircularArc2d)c1).SetAngles(0,2*Math.PI);
}
if (c2 is CircularArc2d) {
((CircularArc2d)c2).SetAngles(0,2*Math.PI);
}
intx.Set(c1,c2);
}
Point2d returnValue = referencePoint;
if (intx.NumberOfIntersectionPoints>0) {
// more than one intersect point, so assume that the one that's closest
// to referencePoint is the one that we want.  This may not be the case
// with large offsets or short parcel segments, but it's usually right.
returnValue = intx.GetIntersectionPoint(0);
for (int i=1; i<intx.NumberOfIntersectionPoints; i++) {
Point2d p = intx.GetIntersectionPoint(i);
if (p.GetDistanceTo(referencePoint) < returnValue.GetDistanceTo(referencePoint))
returnValue=p;
}
}
return returnValue;
}