using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
 
namespace electricalPlugin
{
  public class test : IExtensionApplication
  {
    [CommandMethod("test")]
    public void Test()
    {
      Document doc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
      if (doc == null) return;
      Database db = doc.Database;
      Editor ed = doc.Editor;
 
      TypedValue[] tv = new TypedValue[1];
      tv.SetValue(new TypedValue((int)DxfCode.Start, "HATCH"), 0);
      SelectionFilter sf = new SelectionFilter(tv);
 
      PromptSelectionResult psr = ed.GetSelection(sf);
      if (psr.Status != PromptStatus.OK) return;
 
      using (Transaction tr = db.TransactionManager.StartTransaction())
      {
        foreach (ObjectId id in psr.Value.GetObjectIds())
        {
          if (id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Hatch))))
          {
            Hatch ent = tr.GetObject(id, OpenMode.ForRead) as Hatch;
            double area = GetHatchArea(ent);
            ed.WriteMessage("\nArea[{0}]={1}",id,area);
          }
        }
        tr.Commit();
      }
    }
 
    double GetHatchArea(Hatch pHatch)
    {
      double area = 0;
      try
      {
        area = pHatch.Area;
      } catch 
      {
        int nLoop = pHatch.NumberOfLoops;
        int loopType;
        for (int i = 0; i < nLoop; i++)
        {
          double looparea = 0;
          loopType = (int)pHatch.LoopTypeAt(i);
          if ((loopType & (int)HatchLoopTypes.Polyline) > 0)
          {
            HatchLoop hatchLoop = pHatch.GetLoopAt(i);
            BulgeVertexCollection bulgeVertex = hatchLoop.Polyline;
            using (Polyline pPoly = new Polyline(bulgeVertex.Count))
            {
              for (int j = 0; j < bulgeVertex.Count; j++)
              {
                pPoly.AddVertexAt(j, bulgeVertex[j].Vertex, bulgeVertex[j].Bulge, 0, 0);
              }
              pPoly.Closed = (loopType & (int)HatchLoopTypes.NotClosed) == 0;
              looparea = pPoly.Area;
              if ((loopType & (int)HatchLoopTypes.External) > 0)
                area += Math.Abs(looparea);
              else
                area -= Math.Abs(looparea);
            }
          } else
          {
            HatchLoop hatchLoop = pHatch.GetLoopAt(i);
            Curve2d[] cur2ds = new Curve2d[hatchLoop.Curves.Count];
            hatchLoop.Curves.CopyTo(cur2ds, 0);
            using (CompositeCurve2d compCurve = new CompositeCurve2d(cur2ds))
            {
              Interval interval = compCurve.GetInterval();
              double dMin = interval.GetBounds()[0], dMax = interval.GetBounds()[1];
              if (Math.Abs(dMax - dMin) > 1e-6)
              {
                try
                {
                  looparea = compCurve.GetArea(dMin, dMax);
                  if ((loopType & (int)HatchLoopTypes.External) > 0)
                    area += Math.Abs(looparea);
                  else
                    area -= Math.Abs(looparea);
                }
                catch
                {
                  // Разбиваем кривую на 1000000 точек. Надеюсь, что такой точности 
                  // будет достаточно.
                  Point2d[] pts = compCurve.GetSamplePoints((int)1e+6);
                  int np = pts.Length;
                  for (int j = 0; j < np; j++)
                  {
                    looparea += 0.5 * pts[j].X * (pts[(j + 1) % np].Y - pts[(j + np - 1) % np].Y);
                  }
                  if ((loopType & (int)HatchLoopTypes.External) > 0)
                    area += Math.Abs(looparea);
                  else
                    area -= Math.Abs(looparea);
                }
              }
            }
          }
        }
      }
      return Math.Abs(area);
    }
 
    public void Initialize()
    {
    }
 
    public void Terminate()
    {
    }
 
  }
}