Beispiel #1
0
        /// <summary>
        /// Process point below over the scanLine
        /// </summary>
        /// <param name="scanLine">Eeference line used to generate
        /// points</param>
        /// <param name="densityOfPoints">Number of points
        /// per AutoCAD unit of drawing</param>
        /// <param name="increaseOnStep">Reprocess when a step
        /// is identified. Used to control recursion</param>
        private static void ProcessScanLine(LineSegment3d scanLine,
                                            int densityOfPoints, bool increaseOnStep)
        {
            PointOnCurve3d[] pointsOnDatum =
                scanLine.GetSamplePoints(
                    (int)(scanLine.Length * densityOfPoints));
            Point3d lastPointAdded = Point3d.Origin;

            foreach (PointOnCurve3d pointOnDatumCurve in pointsOnDatum)
            {
                Point3d pointOnDatum = new Point3d(
                    pointOnDatumCurve.Point.ToArray());
                double elevationOnSurface =
                    (_surface != null ?
                     _surface.FindElevationAtXY(pointOnDatum.X, pointOnDatum.Y) : // up to elevation of the reference surface
                     _upperLimit);                                                // up to the limit
                Point3d pointOnSurface = new Point3d(
                    pointOnDatum.X, pointOnDatum.Y, elevationOnSurface);

                // check if this point is below the solid
                // by how many hits a vertical line from
                // this point hit the solid. The lower
                // Z value is the one.
                LinearEntity3d lineEnt = new LineSegment3d(
                    pointOnDatum, pointOnSurface);
                Hit[] hits = _brepSolid.GetLineContainment(lineEnt, 1);
                if (hits != null)
                {
                    double lowerZ = hits[0].Point.Z; //double.MaxValue;
                    //foreach (Hit h in hits)
                    //{
                    //  if (h.Point.Z < lowerZ)
                    //    lowerZ = h.Point.Z;
                    //  h.Dispose();
                    //}
                    Point3d pointToAdd = new Point3d(
                        pointOnDatum.X, pointOnDatum.Y, lowerZ);
                    _newPoints.Add(pointToAdd);

                    // increase density on steps (big change on elevation)?
                    // ToDo: Need to implement that on the other direction.
                    //       This is working only over the scan line direction,
                    //       but is also required on the perpendicular
                    if (increaseOnStep)
                    {
                        //skip very first point
                        if (lastPointAdded.DistanceTo(Point3d.Origin) != 0)
                        {
                            if (pointToAdd.DistanceTo(lastPointAdded) >
                                ((1.0 / densityOfPoints) * 10))
                            {
                                double  scanLineElevation = scanLine.StartPoint.Z;
                                Point3d scanLinePt1       = new Point3d(
                                    lastPointAdded.X, lastPointAdded.Y,
                                    scanLineElevation);
                                Point3d scanLinePt2 = new Point3d(
                                    pointToAdd.X, pointToAdd.Y, scanLineElevation);
                                LineSegment3d increaseScanLine = new LineSegment3d(
                                    scanLinePt1, scanLinePt2);
                                ProcessScanLine(increaseScanLine,
                                                densityOfPoints * 10, false);
                                increaseScanLine.Dispose();
                            }
                        }
                        lastPointAdded = pointToAdd;
                    }
                }
                pointOnDatumCurve.Dispose();
            }
        }
Beispiel #2
0
 public override void Dispose() =>
 ncadSegment.Dispose();
Beispiel #3
0
        /// <summary>
        /// Scan the solid from bottom, identify points and create
        /// a surface
        /// </summary>
        /// <param name="solidId">Solid to scan</param>
        /// <param name="tinSurfaceToCutId">Referecen surface</param>
        /// <param name="solidSurfaceName">Name of the new
        /// surface that will be created</param>
        /// <param name="densityOfPoints">Number of points per
        /// AutoCAD unit used on scan</param>
        /// <param name="simplifySurface">Whether o not simplify
        /// the surface at the end (using Civil 3D
        /// built-in operation)</param>
        private static void GenerateSurfaceByScan(
            ObjectId solidId,
            ObjectId tinSurfaceToCutId,
            string solidSurfaceName,
            int densityOfPoints,
            bool simplifySurface)
        {
            _db = Application.DocumentManager.MdiActiveDocument.Database;
            using (_trans = _db.TransactionManager.StartTransaction())
            {
                try
                {
                    // open entities
                    _solid = _trans.GetObject(solidId, OpenMode.ForRead)
                             as Solid3d;
                    if (!tinSurfaceToCutId.IsNull)
                    {
                        _surface =
                            _trans.GetObject(tinSurfaceToCutId, OpenMode.ForRead)
                            as TinSurface;
                    }

                    // extract the Brep of the solid
                    _brepSolid = new Brep(_solid);
                    _newPoints = new Point3dCollection();

                    // get the extend of the solid
                    Extents3d extends = _solid.GeometricExtents;
                    // and expand by 20% to increase accuracy
                    // on the solid edges/borders
                    extends.TransformBy(Matrix3d.Scaling(1.2,
                                                         _solid.MassProperties.Centroid));

                    // geometric line at the bottom (virtual datum)
                    // this line is the scan line
                    //
                    //  x--------------------------x
                    //  |  pt2        ^            pt3
                    //  |             direction
                    //  |             of scan progress
                    //  |
                    //  | <-scan line
                    //  |
                    //  x  pt1
                    //
                    Point3d scanLinePt1 = extends.MinPoint;
                    Point3d scanLinePt2 = new Point3d(
                        scanLinePt1.X, extends.MaxPoint.Y, scanLinePt1.Z);
                    LineSegment3d scanLine = new LineSegment3d(
                        scanLinePt1, scanLinePt2);
                    Point3d scanLinePt3 = new Point3d(
                        extends.MaxPoint.X, extends.MaxPoint.Y, scanLinePt1.Z);
                    _upperLimit = extends.MaxPoint.Z; // scan upper limit

                    int numberOfScanLines = ((int)
                                             Math.Round(scanLinePt2.DistanceTo(scanLinePt3),
                                                        MidpointRounding.ToEven)) * densityOfPoints;

                    ProgressMeter progressBar = new ProgressMeter();
                    progressBar.SetLimit(numberOfScanLines);
                    progressBar.Start("Scanning solid...");

                    for (int i = 0; i < numberOfScanLines; i++)
                    {
                        ProcessScanLine(scanLine, densityOfPoints, true);

                        // move the scan line over the scane direction
                        // get direction vector
                        Vector3d scanLineDisplacementDirection =
                            scanLinePt2.GetVectorTo(scanLinePt3);
                        // make unit vector
                        scanLineDisplacementDirection /=
                            scanLineDisplacementDirection.Length;
                        // adjust size
                        scanLineDisplacementDirection *=
                            (1.0 / densityOfPoints);
                        scanLine.TransformBy(Matrix3d.Displacement(
                                                 scanLineDisplacementDirection));

                        progressBar.MeterProgress();
                        Util.AvoidNotResponding();
                    }
                    progressBar.Stop();
                    scanLine.Dispose();

                    #region For testing only
#if DEBUG
                    BlockTableRecord mSpace = _trans.GetObject(_db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                    foreach (Point3d pt in _newPoints)
                    {
                        DBPoint p = new DBPoint(pt);
                        mSpace.AppendEntity(p);
                        _trans.AddNewlyCreatedDBObject(p, true);
                    }
#endif
                    #endregion

                    CreateSolidSurface(solidSurfaceName, simplifySurface);

                    _trans.Commit();
                }
                catch (System.Exception ex)
                {
                    Application.DocumentManager.MdiActiveDocument.
                    Editor.WriteMessage("Error: Operation aborted ({0})",
                                        ex.Message);
                    _trans.Abort();
                }
                finally
                {
                    // final cleanup
                    if (!_brepSolid.IsDisposed)
                    {
                        _brepSolid.Dispose();
                    }
                    if (!_newPoints.IsDisposed)
                    {
                        _newPoints.Dispose();
                    }
                    _solid     = null;
                    _surface   = null;
                    _brepSolid = null;
                    _newPoints = null;
                }
            }
        }