Thursday, November 19, 2009

(VII) New SDO_GEOMETRY <-> Autodesk Map3d 2010

Author: Jonio, Dennis

The next and last items on the list ...
  • Given one or more Autodesk/Map3d objects decompose it(them) into “Drawable(s)”.
  • Given a “DrawAble” compose a Autodesk/Map3d object.

    This is the class that interacts with Autodesk Map3d. (I have removed a few things that are not importtant to the discussion here.)
    First, as time has gone on I have grown weary of parseing out Autodesk/Map3d objects and manipulating them. I gravitated toward AppendLoopFromBoundary() and BalanceTree() for MPolygon construction. Just a lot less code on my part. If it isn't a Point type I force just about everything to a Polyline at one time or the other. If you really need true 3D objects you shouldn't be reading this anyway.
    Just some things of note:
  • I never output an Oracle Circle
  • I never output an Oracle Rectangle
  • I never output an Oracle SDO_POINT
    I will read them and write them as Autdesk objects but after this they loose their identity as such.

    This is the last post on this topic. I have decided NOT to post the working source and project. If you are interested in the final work leave a comment with your email address.

    Since I produce only VALIDATED geometry I will be working on the post of my latest iteration of my IO class for doing validation against the database.
    Source code (C#):

    using MDADDrawAbles;
    using SDO = MDADDrawAbles.DrawAbleSdoGeometryUtil;

    using NetSdoGeometry;

    namespace MDADDrawAbleDwg
    {
    public class DrawAbleDwg
    {
    //
    // POINT
    //
    public static DrawAble PointDrawAbleFromPoint(Point3d p3d, int _dimensionality)
    {
    DrawAble dp = new DrawAble(DrawAbleType.Point, _dimensionality);
    DrawAbleSubComponent dpc = new DrawAbleSubComponent();
    dpc.Etype = DrawAbleSubComponentEType.Point;
    int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;
    dpc.Ords = new decimal[len];
    dpc.Ords[0] = System.Convert.ToDecimal(p3d.X);
    dpc.Ords[1] = System.Convert.ToDecimal(p3d.Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dpc.Ords[2] = System.Convert.ToDecimal(p3d.Z);
    dp.SubComponents.Add(dpc);
    return dp;
    }
    public static DrawAble PointDrawAbleFromPoint(DBPoint dbp, int _dimensionality)
    {
    DrawAble dp = new DrawAble(DrawAbleType.Point, _dimensionality);
    DrawAbleSubComponent dpc = new DrawAbleSubComponent();
    dpc.Etype = DrawAbleSubComponentEType.Point;
    int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;
    dpc.Ords = new decimal[len];
    dpc.Ords[0] = System.Convert.ToDecimal(dbp.Position.X);
    dpc.Ords[1] = System.Convert.ToDecimal(dbp.Position.Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dpc.Ords[2] = System.Convert.ToDecimal(dbp.Position.Z);
    dp.SubComponents.Add(dpc);
    return dp;
    }
    //
    // POINT CLUSTER
    //
    public static DrawAble PointClusterDrawAbleFromPointList(List p3dList, int _dimensionality)
    {
    DrawAble dp = new DrawAble(DrawAbleType.Point, _dimensionality);
    DrawAbleSubComponent dpc = new DrawAbleSubComponent();
    dpc.Etype = DrawAbleSubComponentEType.PointCluster;
    int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;
    dpc.Ords = new decimal[len * p3dList.Count];
    int p3d_counter = 0;
    for (int _k = 0; _k < dpc.Ords.Length; )
    {
    dpc.Ords[_k] = System.Convert.ToDecimal(p3dList[p3d_counter].X);
    dpc.Ords[_k + 1] = System.Convert.ToDecimal(p3dList[p3d_counter].Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dpc.Ords[_k + 2] = System.Convert.ToDecimal(p3dList[p3d_counter].Z);
    _k = _k + len;
    p3d_counter = p3d_counter + 1;
    }
    dpc.Elem = new int[] { 0, 1, p3dList.Count };
    dp.SubComponents.Add(dpc);
    return dp;
    }
    //
    // LINES
    //
    public static DrawAble LineCurveDrawAbleFromPolyline(Polyline pl, Polyline2d pl2d, Polyline3d pl3d, int _dimensionality)
    {
    DrawAble dl = new DrawAble(DrawAbleType.Line, _dimensionality);
    int hasBulgesCount = 0;
    Point3dCollection tmppts = null;
    DoubleCollection tmpblgs = null;
    Point3d[] pts = null;
    double[] blgs = null;
    if (pl != null)
    {
    tmppts = new Point3dCollection();
    tmpblgs = new DoubleCollection();
    int i = 0;
    for (; i < pl.NumberOfVertices; i++)
    {
    switch (pl.GetSegmentType(i))
    {
    case SegmentType.Arc:
    CircularArc2d ca2d = pl.GetArcSegment2dAt(i);
    double bulge = GetBulge2d(ca2d);
    tmpblgs.Add(bulge);
    tmppts.Add(new Point3d(ca2d.StartPoint.X, ca2d.StartPoint.Y, pl.GetPoint3dAt(i).Z));
    hasBulgesCount++;
    ca2d.Dispose();
    break;
    default:
    tmpblgs.Add(0.0);
    tmppts.Add(new Point3d(pl.GetPoint3dAt(i).X, pl.GetPoint3dAt(i).Y, pl.GetPoint3dAt(i).Z));
    break;
    }
    }
    // Do NOT duplicate any point ... this appears to have different behavior for
    // the 2D and 3D polylines so we will check them all.
    if (pl.Closed && (tmppts[0].IsEqualTo(tmppts[tmppts.Count - 1]) == false))
    {
    //tmppts.Add(new Point3d(pl.GetPoint2dAt(0).X, pl.GetPoint2dAt(0).Y, 0.0));
    tmppts.Add(new Point3d(pl.GetPoint3dAt(0).X, pl.GetPoint3dAt(0).Y, pl.GetPoint3dAt(0).Z));
    tmpblgs.Add(0.0);
    }
    // Now we can dimensions our array stuctures and fill them up
    pts = new Point3d[tmppts.Count];
    blgs = new double[tmppts.Count];
    for (int z = 0; z < tmppts.Count; z++)
    {
    pts[z] = new Point3d(tmppts[z].X, tmppts[z].Y, tmppts[z].Z);
    blgs[z] = tmpblgs[z];
    }
    tmppts.Clear();
    tmppts.Dispose();
    tmpblgs.Clear();
    }
    //END OF POLYLINE
    //START OF POLYLINE2D
    if (pl2d != null)
    {
    // No way of knowing how many we have so we need this to collect the points
    tmppts = new Point3dCollection();
    tmpblgs = new DoubleCollection();
    if (pl2d.PolyType == Poly2dType.SimplePoly)
    {
    Transaction t = pl2d.Database.TransactionManager.StartTransaction();
    IEnumerator iterate = pl2d.GetEnumerator();
    while (iterate.MoveNext())
    {
    ObjectId id = (ObjectId)iterate.Current;
    Vertex2d vertex = (Vertex2d)t.GetObject(id, OpenMode.ForRead);
    tmppts.Add(vertex.Position);
    tmpblgs.Add(vertex.Bulge);
    if (vertex.Bulge != 0.0)
    hasBulgesCount++;
    }
    t.Abort();
    t.Dispose();
    }
    else
    {
    DBObjectCollection collection = new DBObjectCollection();
    pl2d.Explode(collection);
    foreach (Line line in collection)
    {
    tmppts.Add(line.StartPoint);
    tmpblgs.Add(0.0);
    tmppts.Add(line.EndPoint);
    tmpblgs.Add(0.0);
    }
    collection.Dispose();
    }
    // Do NOT duplicate any point
    if (pl2d.Closed && (tmppts[0].IsEqualTo(tmppts[tmppts.Count - 1]) == false))
    {
    tmppts.Add(tmppts[0]);
    tmpblgs.Add(0.0);
    }
    // Now we can dimensions our array stuctures and fill them up
    pts = new Point3d[tmppts.Count];
    blgs = new double[tmppts.Count];
    for (int z = 0; z < tmppts.Count; z++)
    {
    pts[z] = new Point3d(tmppts[z].X, tmppts[z].Y, tmppts[z].Z);
    blgs[z] = tmpblgs[z];
    }
    tmppts.Clear();
    tmppts.Dispose();
    tmpblgs.Clear();
    }
    //END OF POLYLINE2D
    //START OF POLYLINE3D
    if (pl3d != null)
    {
    tmppts = new Point3dCollection();
    tmpblgs = new DoubleCollection();
    if (pl3d.PolyType == Poly3dType.SimplePoly)
    {
    Transaction t = pl3d.Database.TransactionManager.StartTransaction();
    IEnumerator iterator = pl3d.GetEnumerator();
    while (iterator.MoveNext())
    {
    ObjectId id = (ObjectId)iterator.Current;
    PolylineVertex3d vertex3d = (PolylineVertex3d)t.GetObject(id, OpenMode.ForRead);
    tmppts.Add(vertex3d.Position);
    tmpblgs.Add(0.0);
    }
    t.Abort();
    t.Dispose();
    }
    else
    {
    DBObjectCollection collection = new DBObjectCollection();
    pl3d.Explode(collection);
    foreach (Line line in collection)
    {
    tmppts.Add(line.StartPoint);
    tmpblgs.Add(0.0);
    tmppts.Add(line.EndPoint);
    tmpblgs.Add(0.0);
    }
    collection.Dispose();
    }
    // Do NOT duplicate any point
    if (pl3d.Closed && (tmppts[0].IsEqualTo(tmppts[tmppts.Count - 1]) == false))
    {
    tmppts.Add(tmppts[0]);
    tmpblgs.Add(0.0);
    }
    // Now we can dimensions our array stuctures and fill them up
    pts = new Point3d[tmppts.Count];
    blgs = new double[tmppts.Count];
    for (int z = 0; z < tmppts.Count; z++)
    {
    pts[z] = new Point3d(tmppts[z].X, tmppts[z].Y, tmppts[z].Z);
    blgs[z] = tmpblgs[z];
    }
    tmppts.Clear();
    tmppts.Dispose();
    tmpblgs.Clear();
    }
    //END OF POLYLINE3D
    //
    // Finished getting all the ordinates and bulges for this linecurve
    //
    DrawAbleSubComponent dlc = new DrawAbleSubComponent();
    if (hasBulgesCount == 0)
    {
    dlc.Etype = DrawAbleSubComponentEType.SimpleLine;
    int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;
    dlc.Ords = new decimal[len * pts.Length];
    int pts_counter = 0;
    for (int _k = 0; _k < dlc.Ords.Length; )
    {
    dlc.Ords[_k] = System.Convert.ToDecimal(pts[pts_counter].X);
    dlc.Ords[_k + 1] = System.Convert.ToDecimal(pts[pts_counter].Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dlc.Ords[_k + 2] = System.Convert.ToDecimal(pts[pts_counter].Z);
    _k = _k + len;
    pts_counter = pts_counter + 1;
    }
    dl.SubComponents.Add(dlc);
    }
    else if (hasBulgesCount == pts.Length - 1)
    {
    dlc.Etype = DrawAbleSubComponentEType.SimpleLineAllCurves;
    int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;
    dlc.Ords = new decimal[(len * pts.Length) + (hasBulgesCount * len)];
    int ords_counter = 0;
    Point3d arc_endpoint;

    for (int j = 0; j < pts.Length; j++)
    {
    double theBulge = blgs[j];
    arc_endpoint = pts[j + 1];
    CircularArc2d ca2d = new CircularArc2d(
    new Point2d(pts[j].X, pts[j].Y),
    new Point2d(arc_endpoint.X, arc_endpoint.Y), theBulge, false);

    Interval interval_of_arc = ca2d.GetInterval();
    Point2d somePointOnArc = ca2d.EvaluatePoint(interval_of_arc.Element / 2);
    //Start
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].X);
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);
    //Center point on arc
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.X);
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);

    //Because of LOOK-AHEAD we now check for the end
    if (j == (pts.Length - 2))
    {
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(arc_endpoint.X);
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(arc_endpoint.Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(arc_endpoint.Z);
    j = pts.Length; //End the loop
    }
    }
    dl.SubComponents.Add(dlc);
    }
    else
    {
    //DIM_ELEMENTS are required
    dlc.Etype = DrawAbleSubComponentEType.CompoundLine;
    int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;
    dlc.Ords = new decimal[(len * pts.Length) + (hasBulgesCount * len)];
    int ords_counter = 0;
    Point3d arc_endpoint;

    TriInts elmHeader = new TriInts(ords_counter, SDO.BasicETYPE(DrawAbleSubComponentEType.CompoundLine), 0);
    List elmList = new List();
    TriInts wrkrElm = null;
    int nxtINTERP = 0;
    int lstINTERP = 0;
    for (int j = 0; j < pts.Length; j++)
    {
    if (j < pts.Length - 1)
    nxtINTERP = (blgs[j] == 0.0) ? (int)SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleLine) : (int)SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleLineAllCurves);

    if (lstINTERP != nxtINTERP)
    {
    if (wrkrElm != null)
    elmList.Add(wrkrElm);
    wrkrElm = new TriInts(ords_counter, SDO.BasicETYPE(DrawAbleSubComponentEType.SimpleLineAllCurves), nxtINTERP);
    lstINTERP = nxtINTERP;
    }

    double theBulge = blgs[j];
    if (theBulge != 0.0)
    {
    arc_endpoint = pts[j + 1];
    CircularArc2d ca2d = new CircularArc2d(
    new Point2d(pts[j].X, pts[j].Y),
    new Point2d(arc_endpoint.X, arc_endpoint.Y), theBulge, false);

    Interval interval_of_arc = ca2d.GetInterval();
    Point2d somePointOnArc = ca2d.EvaluatePoint(interval_of_arc.Element / 2);
    //Start
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].X);
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);
    //Center point on arc
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.X);
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);
    }
    else
    {
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].X);
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);
    }

    }//for loop
    elmList.Add(wrkrElm);
    elmHeader.INTERP = elmList.Count;
    dlc.Elem = new int[(elmList.Count + 1) * 3];
    int cntr = 0;
    dlc.Elem[cntr++] = elmHeader.OFFSET;
    dlc.Elem[cntr++] = elmHeader.ETYPE;
    dlc.Elem[cntr++] = elmHeader.INTERP;
    for (int _i = 0; _i < elmList.Count; _i++)
    {
    dlc.Elem[cntr++] = elmList[_i].OFFSET;
    dlc.Elem[cntr++] = elmList[_i].ETYPE;
    dlc.Elem[cntr++] = elmList[_i].INTERP;
    }
    dl.SubComponents.Add(dlc);
    }
    return dl;
    }
    public static DrawAble LineCurveDrawAbleFromArc(Arc a, int _dimensionality)
    {
    DrawAble d = new DrawAble(DrawAbleType.Line, _dimensionality);
    DrawAbleSubComponent dc = new DrawAbleSubComponent();
    dc.Etype = DrawAbleSubComponentEType.SimpleLineAllCurves;
    int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;
    dc.Ords = new decimal[len * 3];
    double length = a.GetDistAtPoint(a.EndPoint);
    Point3d mid = a.GetPointAtDist(length / 2.0);
    int ords_counter = 0;
    //Start
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.StartPoint.X);
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.StartPoint.Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.StartPoint.Z);
    //Mid
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(mid.X);
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(mid.Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(mid.Z);
    //End
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.EndPoint.X);
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.EndPoint.Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(a.EndPoint.Z);
    d.SubComponents.Add(dc);

    return d;
    }
    public static DrawAble LineCurveDrawAbleFromLine(Line l, int _dimensionality)
    {
    DrawAble d = new DrawAble(DrawAbleType.Line, _dimensionality);
    DrawAbleSubComponent dc = new DrawAbleSubComponent();
    dc.Etype = DrawAbleSubComponentEType.SimpleLine;
    int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;
    dc.Ords = new decimal[len * 2];
    int ords_counter = 0;
    //Start
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.StartPoint.X);
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.StartPoint.Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.StartPoint.Z);
    //End
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.EndPoint.X);
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.EndPoint.Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(l.EndPoint.Z);
    d.SubComponents.Add(dc);

    return d;
    }
    public static DrawAble LineCurveDrawAbleFromCircle(Circle circ, int _dimensionality)
    {
    DrawAble d = new DrawAble(DrawAbleType.Line, _dimensionality);
    DrawAbleSubComponent dc = new DrawAbleSubComponent();
    dc.Etype = DrawAbleSubComponentEType.SimpleLineAllCurves;
    int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? 15 : 10;
    dc.Ords = new decimal[len];
    int ords_counter = 0;
    double length = circ.Circumference;
    Point3d firstarc_endpoint = circ.GetPointAtDist(length / 2.0);
    Point3d firstarc_midpoint = circ.GetPointAtDist((length / 2.0) / 2.0);
    Point3d secondarc_midpoint = circ.GetPointAtDist(length * .75);
    //Start
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.StartPoint.X);
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.StartPoint.Y);
    if (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.StartPoint.Z);
    //mid 1
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_midpoint.X);
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_midpoint.Y);
    if (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_midpoint.Z);
    //End
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_endpoint.X);
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_endpoint.Y);
    if (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(firstarc_endpoint.Z);
    //mid 2
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(secondarc_midpoint.X);
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(secondarc_midpoint.Y);
    if (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(secondarc_midpoint.Z);
    //End
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.EndPoint.X);
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.EndPoint.Y);
    if (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dc.Ords[ords_counter++] = System.Convert.ToDecimal(circ.EndPoint.Z);

    d.SubComponents.Add(dc);

    return d;
    }
    //
    // SURFACES
    //
    public static DrawAble PolygonDrawAbleFromMPolygon(MPolygon mpoly, int _dimensionality)
    {
    DrawAble dl = new DrawAble(DrawAbleType.Surface, _dimensionality);
    Point3dCollection p3dColl = new Point3dCollection();
    LoopDirection loopdirection;
    int ords_counter = 0; // The total ordinates in the array
    int hasBulgesCount = 0;
    int loops = mpoly.NumMPolygonLoops;
    for (int i = 0; i < loops; i++)
    {
    // Gather up points and bulges for this loop
    MPolygonLoop mPolygonLoop = mpoly.GetMPolygonLoopAt(i);
    loopdirection = mpoly.GetLoopDirection(i);
    hasBulgesCount = 0;
    ords_counter = 0;
    // Remove duplicate verticies
    for (int d = 1; d < mPolygonLoop.Count - 1; d++)
    {
    if (mPolygonLoop[d].Vertex.IsEqualTo(mPolygonLoop[d + 1].Vertex))
    {
    mPolygonLoop.RemoveAt(d + 1);
    }
    }
    //
    Point3d[] pts = new Point3d[mPolygonLoop.Count];
    double[] blgs = new double[mPolygonLoop.Count];
    for (int z = 0; z < mPolygonLoop.Count; z++)
    {
    if (z == mPolygonLoop.Count - 1)
    {
    pts[z] = pts[0];
    }
    else
    {
    double X = Math.Round(mPolygonLoop[z].Vertex.X, 10, MidpointRounding.AwayFromZero);
    double Y = Math.Round(mPolygonLoop[z].Vertex.Y, 10, MidpointRounding.AwayFromZero);
    double Z = Math.Round(mpoly.Elevation, 10, MidpointRounding.AwayFromZero);
    pts[z] = new Point3d(X, Y, Z);
    }
    blgs[z] = mPolygonLoop[z].Bulge;
    if (blgs[z] != 0.0)
    hasBulgesCount = hasBulgesCount + 1;
    }
    //
    // Suspect code here ......
    //
    if (blgs[0] == blgs[mPolygonLoop.Count - 1] && blgs[0] != 0.0)
    {
    blgs[mPolygonLoop.Count - 1] = 0.0;
    hasBulgesCount--;
    }
    //
    //DO THE STUFF
    //
    DrawAbleSubComponent dlc = new DrawAbleSubComponent();
    TriInts headerElem = new TriInts(ords_counter, 0, 0);
    if (hasBulgesCount == 0)
    {
    headerElem.INTERP = SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine);
    }
    //else if (hasBulgesCount == pts.Length)
    else if (hasBulgesCount == pts.Length - 1)
    {
    headerElem.INTERP = SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves);
    }

    if (loopdirection == LoopDirection.Exterior)
    {
    if (headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine) ||
    headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves))
    {
    headerElem.ETYPE = SDO.BasicETYPE(DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine);
    if (headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine))
    dlc.Etype = DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine;
    else
    dlc.Etype = DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves;
    }
    }
    else
    {

    if (headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine) ||
    headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves))
    {
    headerElem.ETYPE = SDO.BasicETYPE(DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine);
    if (headerElem.INTERP == SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine))
    dlc.Etype = DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine;
    else
    dlc.Etype = DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves;
    }
    }
    // If we have not set the etype it must be a 1005 0R 2005 - compound polygon
    if (headerElem.ETYPE == 0 && hasBulgesCount > 0)
    {
    if (loopdirection == LoopDirection.Exterior)
    {
    headerElem.ETYPE = SDO.BasicETYPE(DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine);
    dlc.Etype = DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine;
    }
    else
    {
    headerElem.ETYPE = SDO.BasicETYPE(DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine);
    dlc.Etype = DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine;
    }
    headerElem.INTERP = 0; // to be set later with count
    }
    //Now we are ready to build the elem and ords
    int len = (_dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D) ? DrawAbleSdoGeometry.DefaultDimensionality3D : DrawAbleSdoGeometry.DefaultDimensionality2D;
    dlc.Ords = new decimal[(len * pts.Length) + (hasBulgesCount * len)];
    List elmList = new List();
    TriInts wrkrElm = null;
    int nxtINTERP = 0;
    int lstINTERP = 0;
    Point3d arc_endpoint;
    for (int j = 0; j < pts.Length; j++)
    {
    if (j < pts.Length - 1)
    nxtINTERP = (blgs[j] == 0.0) ? SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleLine) : SDO.BasicINTERPRETATION(DrawAbleSubComponentEType.SimpleLineAllCurves);

    if (lstINTERP != nxtINTERP)
    {
    if (wrkrElm != null)
    elmList.Add(wrkrElm);
    wrkrElm = new TriInts(ords_counter,
    SDO.BasicETYPE((blgs[j] == 0.0) ? DrawAbleSubComponentEType.SimpleLine : DrawAbleSubComponentEType.SimpleLineAllCurves),
    nxtINTERP);
    lstINTERP = nxtINTERP;
    }

    double theBulge = blgs[j];
    if (theBulge != 0.0)
    {
    arc_endpoint = pts[j + 1];
    CircularArc2d ca2d = new CircularArc2d(
    new Point2d(pts[j].X, pts[j].Y),
    new Point2d(arc_endpoint.X, arc_endpoint.Y), theBulge, false);

    Interval interval_of_arc = ca2d.GetInterval();
    Point2d somePointOnArc = ca2d.EvaluatePoint(interval_of_arc.Element / 2);
    //Start
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].X);
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);
    //Center point on arc
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.X);
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(somePointOnArc.Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);
    }
    else
    {
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].X);
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Y);
    if (len == DrawAbleSdoGeometry.DefaultDimensionality3D)
    dlc.Ords[ords_counter++] = System.Convert.ToDecimal(pts[j].Z);
    }

    }//for loop of ordinates
    int elem_cntr = 0;
    if (headerElem.ETYPE == SDO.BasicETYPE(DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine) ||
    headerElem.ETYPE == SDO.BasicETYPE(DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine))
    {
    //Add our last worker element
    elmList.Add(wrkrElm);
    //Update the count in the header
    headerElem.INTERP = elmList.Count;
    //Dimension the array = element list count + one(1) for header "times" three(3)
    dlc.Elem = new int[(elmList.Count + 1) * 3];
    dlc.Elem[elem_cntr++] = headerElem.OFFSET;
    dlc.Elem[elem_cntr++] = headerElem.ETYPE;
    dlc.Elem[elem_cntr++] = headerElem.INTERP;
    for (int _i = 0; _i < elmList.Count; _i++)
    {
    dlc.Elem[elem_cntr++] = elmList[_i].OFFSET;
    dlc.Elem[elem_cntr++] = elmList[_i].ETYPE;
    dlc.Elem[elem_cntr++] = elmList[_i].INTERP;
    }
    }
    else
    {
    dlc.Elem = new int[3];
    dlc.Elem[elem_cntr++] = headerElem.OFFSET;
    dlc.Elem[elem_cntr++] = headerElem.ETYPE;
    dlc.Elem[elem_cntr++] = headerElem.INTERP;
    }
    dl.SubComponents.Add(dlc);
    }//next ring in the MPolygon

    return dl;
    }
    //
    // Returns: List, DBPoint, Polyline, MPolygon
    //
    public static object DrawAbleDwgObj(DrawAble drawable)
    {
    bool firstPointFlag = false;
    int IncrementFor3d = 0;
    if (drawable.Dimensionality == MDADDrawAbles.DrawAbleSdoGeometry.DefaultDimensionality3D)
    IncrementFor3d = 1;
    MPolygon dbMpoly = null;
    Polyline plineCurves = null;
    Polyline plineCompound = null;
    Polyline plineLine = null;
    DBPoint dbPoint = null;
    List dbPointList = null;

    //Turn the dim elements into triplets for easy use
    List elmsList = null;
    int CountOfComponents = drawable.SubComponents.Count;
    foreach (DrawAbleSubComponent cmp in drawable.SubComponents)
    {
    if (cmp.Elem != null)
    {
    elmsList = new List();
    for (int _i = 0; _i < cmp.Elem.Length; )
    {
    TriInts t = new TriInts(cmp.Elem[_i + 0], cmp.Elem[_i + 1], cmp.Elem[_i + 2]);
    elmsList.Add(t);
    _i = _i + 3;
    }
    }
    else
    elmsList = null;
    //Turn all the decimals into doubles
    double[] ords = new double[cmp.Ords.Length];
    for (int j = 0; j < cmp.Ords.Length; j++)
    ords[j] = System.Convert.ToDouble(cmp.Ords[j]);

    DrawAbleSubComponentEType etype = cmp.Etype;
    firstPointFlag = false;

    //
    //Compound components
    //These require a header and fixup of the components dim element array
    //
    if (cmp.Etype == DrawAbleSubComponentEType.CompoundLine ||
    cmp.Etype == DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine ||
    cmp.Etype == DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine)
    {
    CircularArc2d ca2d;
    Point2d firstPoint2d = new Point2d();
    Point2d begPoint2d = new Point2d();
    Point2d arrowPoint2d, endPoint2d;

    plineCompound = new Polyline();

    //We know what it is because of Etype. We just really need the INTERPs and OFFSETs. Skip to one(1)
    for (int _k = 1; _k < elmsList.Count; )
    {
    TriInts t = elmsList[_k]; int OFFSET = t.OFFSET; int ETYPE = t.ETYPE; int INTERP = t.INTERP;
    int nxtOFFSET = 0;
    if (_k < elmsList.Count - 1)
    nxtOFFSET = elmsList[_k + 1].OFFSET;
    else
    nxtOFFSET = ords.Length;
    for (int x = OFFSET; x < nxtOFFSET; )
    {
    double bulgeValue = 0.0;
    if (firstPointFlag == false) { firstPoint2d = new Point2d(ords[x], ords[x + 1]); firstPointFlag = true; }
    if (INTERP == 2)
    {
    begPoint2d = new Point2d(ords[x++], ords[x++]); x = x + IncrementFor3d;
    //Only if we are not at the end. We ended the line with an arc.
    if (x < nxtOFFSET)
    {
    arrowPoint2d = new Point2d(ords[x++], ords[x++]); x = x + IncrementFor3d;
    endPoint2d = new Point2d(ords[x], ords[x + 1]);
    ca2d = new CircularArc2d(begPoint2d, arrowPoint2d, endPoint2d);
    bulgeValue = GetBulge2d(ca2d);
    ca2d.Dispose();
    }
    plineCompound.AddVertexAt(plineCompound.NumberOfVertices, begPoint2d, bulgeValue, 0, 0);
    if (drawable.Dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)
    plineCompound.Elevation = ords[x - 1];
    }
    else
    {
    begPoint2d = new Point2d(ords[x++], ords[x++]); x = x + IncrementFor3d;
    plineCompound.AddVertexAt(plineCompound.NumberOfVertices, begPoint2d, 0.0, 0.0, 0.0);
    if (drawable.Dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)
    plineCompound.Elevation = ords[x - 1];
    }
    }
    _k = _k + 1;
    }
    if (firstPoint2d == begPoint2d)
    plineCompound.Closed = true;

    if (cmp.Etype == DrawAbleSubComponentEType.CompoundSurfaceInnerRingLine ||
    cmp.Etype == DrawAbleSubComponentEType.CompoundSurfaceOuterRingLine)
    {
    if (dbMpoly == null)
    {
    dbMpoly = new MPolygon();
    }
    dbMpoly.AppendLoopFromBoundary(plineCompound, false, 0.005);
    dbMpoly.BalanceTree();
    plineCompound.Dispose();
    plineCompound = null;
    }
    }
    //
    //Point and PointCluster
    //
    if (cmp.Etype == DrawAbleSubComponentEType.Point)
    {
    Point3d p3d;
    if (IncrementFor3d == 1)
    p3d = new Point3d(ords[0], ords[1], ords[2]);
    else
    p3d = new Point3d(ords[0], ords[1], 0.0);
    dbPoint = new DBPoint(p3d);
    }
    else if (cmp.Etype == DrawAbleSubComponentEType.PointCluster)
    {
    Point3d p3d;
    dbPointList = new List();

    for (int _x = 0; _x < ords.Length; )
    {
    if (IncrementFor3d == 1)
    p3d = new Point3d(ords[_x++], ords[_x++], ords[_x++]);
    else
    p3d = new Point3d(ords[_x++], ords[_x++], 0.0);
    dbPoint = new DBPoint(p3d);
    dbPointList.Add(dbPoint);
    }
    }
    //
    //Simple lines
    //
    if (cmp.Etype == DrawAbleSubComponentEType.SimpleLine ||
    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine ||
    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine)
    {
    Point2d begPoint2d = new Point2d();
    Point2d firstPoint2d = new Point2d();
    plineLine = new Polyline();

    for (int _x = 0; _x < ords.Length; )
    {
    if (firstPointFlag == false) { firstPoint2d = new Point2d(ords[0], ords[1]); firstPointFlag = true; }
    begPoint2d = new Point2d(ords[_x++], ords[_x++]); _x = _x + IncrementFor3d;
    plineLine.AddVertexAt(plineLine.NumberOfVertices, begPoint2d, 0.0, 0.0, 0.0);
    if (drawable.Dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)
    plineLine.Elevation = ords[_x - 1];
    }
    if (firstPoint2d == begPoint2d)
    plineLine.Closed = true;

    if (cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingLine ||
    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingLine)
    {
    if (dbMpoly == null)
    {
    dbMpoly = new MPolygon();
    }
    dbMpoly.AppendLoopFromBoundary(plineLine, false, 0.005);
    dbMpoly.BalanceTree();
    plineLine.Dispose();
    plineLine = null;
    }
    }
    //
    //Simple Curves
    //
    if (cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves ||
    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves ||
    cmp.Etype == DrawAbleSubComponentEType.SimpleLineAllCurves)
    {
    CircularArc2d ca2d;
    Point2d begPoint2d = new Point2d();
    Point2d firstPoint2d = new Point2d();
    Point2d arrowPoint2d, endPoint2d;
    plineCurves = new Polyline();
    //We know what it is because of Etype. We just really need the INTERPs and OFFSETs. Skip to one(1)
    for (int _x = 0; _x < ords.Length; )
    {
    if (firstPointFlag == false) { firstPoint2d = new Point2d(ords[0], ords[1]); firstPointFlag = true; }
    begPoint2d = new Point2d(ords[_x++], ords[_x++]); _x = _x + IncrementFor3d;
    double bulgeValue = 0.0;
    if (_x < ords.Length)
    {
    arrowPoint2d = new Point2d(ords[_x++], ords[_x++]); _x = _x + IncrementFor3d;
    endPoint2d = new Point2d(ords[_x], ords[_x + 1]);
    ca2d = new CircularArc2d(begPoint2d, arrowPoint2d, endPoint2d);
    bulgeValue = GetBulge2d(ca2d);
    ca2d.Dispose();
    }
    plineCurves.AddVertexAt(plineCurves.NumberOfVertices, begPoint2d, bulgeValue, 0, 0);
    if (drawable.Dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)
    plineCurves.Elevation = ords[_x - 1];
    }
    if (firstPoint2d == begPoint2d)
    plineCurves.Closed = true;

    if (cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingAllCurves ||
    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingAllCurves)
    {
    if (dbMpoly == null)
    {
    dbMpoly = new MPolygon();
    }
    dbMpoly.AppendLoopFromBoundary(plineCurves, false, 0.005);
    dbMpoly.BalanceTree();
    plineCurves.Dispose();
    plineCurves = null;
    }
    }
    //
    // Circle
    //
    if (cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingCircle ||
    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingCircle)
    {
    Circle circleSurf = null;
    Point2d a = new Point2d(ords[0], ords[1]);
    Point2d b = new Point2d(ords[2 + IncrementFor3d], ords[3 + IncrementFor3d]);
    Point2d c = new Point2d(ords[4 + IncrementFor3d + IncrementFor3d], ords[5 + IncrementFor3d + IncrementFor3d]);
    double A = b.X - a.X;
    double B = b.Y - a.Y;
    double C = c.X - a.X;
    double D = c.Y - a.Y;

    double E = A * (a.X + b.X) + B * (a.Y + b.Y);
    double F = C * (a.X + c.X) + D * (a.Y + c.Y);
    double G = 2.0 * (A * (c.Y - b.Y) - B * (c.X - b.X));

    if (G != 0)
    {
    double pX = (D * E - B * F) / G;
    double pY = (A * F - C * E) / G;

    // r^2 = (a.X - pX) ^ 2.0 + (a.Y - pY) ^ 2.0
    double radiusSqd = Math.Pow((a.X - pX), 2.0) + Math.Pow((a.Y - pY), 2.0);
    double radius = Math.Sqrt(radiusSqd);

    Point3d p3d_center = new Point3d(pX, pY, 0.0);
    circleSurf = new Circle(p3d_center, new Vector3d(0.0, 0.0, 1.0), radius);
    }
    if (dbMpoly == null)
    {
    dbMpoly = new MPolygon();
    }
    dbMpoly.AppendLoopFromBoundary(circleSurf, false, 0.005);
    dbMpoly.BalanceTree();
    circleSurf.Dispose();
    circleSurf = null;
    }
    //
    //Rectangle
    //
    if (cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceInnerRingRectangle ||
    cmp.Etype == DrawAbleSubComponentEType.SimpleSurfaceOuterRingRectangle)
    {
    Polyline plineRect = new Polyline();
    Point2d sw2d = new Point2d(ords[0], ords[1]);
    Point2d se2d = new Point2d(ords[2 + IncrementFor3d], ords[1]);
    Point2d ne2d = new Point2d(ords[2 + IncrementFor3d], ords[3 + IncrementFor3d]);
    Point2d nw2d = new Point2d(ords[0], ords[3 + IncrementFor3d]);
    Point2d closer2d = new Point2d(ords[0], ords[1]);
    plineRect.AddVertexAt(plineRect.NumberOfVertices, sw2d, 0.0, 0.0, 0.0);
    plineRect.AddVertexAt(plineRect.NumberOfVertices, se2d, 0.0, 0.0, 0.0);
    plineRect.AddVertexAt(plineRect.NumberOfVertices, ne2d, 0.0, 0.0, 0.0);
    plineRect.AddVertexAt(plineRect.NumberOfVertices, nw2d, 0.0, 0.0, 0.0);
    plineRect.AddVertexAt(plineRect.NumberOfVertices, closer2d, 0.0, 0.0, 0.0);
    plineRect.Closed = true;
    if (drawable.Dimensionality == DrawAbleSdoGeometry.DefaultDimensionality3D)
    plineRect.Elevation = ords[2];
    if (dbMpoly == null)
    {
    dbMpoly = new MPolygon();
    }
    dbMpoly.AppendLoopFromBoundary(plineRect, false, 0.005);
    dbMpoly.BalanceTree();
    plineRect.Dispose();
    plineRect = null;
    }

    }//Do the next subcomponent
    if (dbMpoly != null)
    return (object)dbMpoly;
    else if (dbPointList != null)
    return (object)dbPointList;
    else if (dbPoint != null)
    return (object)dbPoint;
    else if (plineLine != null)
    return (object)plineLine;
    else if (plineCurves != null)
    return (object)plineCurves;
    else if (plineCompound != null)
    return (object)plineCompound;
    else
    return null;

    }

    public static double GetBulge2d(CircularArc2d ca2d)
    {
    double theBulge = 0.0;
    if (ca2d.IsClockWise == true)
    {
    theBulge = -Math.Tan((ca2d.EndAngle - ca2d.StartAngle) / 4);
    }
    else
    {
    theBulge = Math.Tan((ca2d.EndAngle - ca2d.StartAngle) / 4);
    }
    return theBulge;
    }

    }//eoc DrawAbleDwg
    }//eons
  • No comments:

    Post a Comment