Author Topic: polyline area  (Read 7445 times)

0 Members and 1 Guest are viewing this topic.

nekitip

  • Guest
Re: polyline area
« Reply #15 on: December 22, 2014, 08:13:30 AM »
i can't really test for C#, since dynamic in VB is sort of native, and (if I remember) keyword doesn't exist in VB, so this code in VB.NET (calling COM)
Code - vb.net: [Select]
  1.        Public Shared Function GetAreaCom(curve As Curve) As Double
  2.            Dim pl = curve.AcadObject
  3.            Return DirectCast(pl.Area, Double)
  4.        End Function        

will run two times slower then .NET code (reading Curve.Area)

but again, COM solution has its problems in overrules so it's usefull only when reading with transaction

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: polyline area
« Reply #16 on: December 22, 2014, 09:31:43 AM »
A quick test shows that the dynamic/COM version is a LOT slower. Although for most uses it would be negligible.
Quote
Command: POLYAREA
Select polyline:
 .NET Area = 5288757.29 in 00:00:00.0030002, COM Area = 5288757.29 in 00:00:01.1790674. (10,000 iterations)

Then editing the GetArea() to check for the selfintersecting polylines, as nekitip suggests, is slower than the .NET version by a fraction:
Quote
.NET Area = 5288757.29 in 00:00:00.0020001, COM Area = 5288757.29 in 00:00:00.2860164. (10,000 iterations)

nekitip

  • Guest
Re: polyline area
« Reply #17 on: December 22, 2014, 10:42:21 AM »
after two days of trial and error, and exploring wast, undocumented namespaces, this may by almost finished!
here is the code that will check if .NET area is correct. If it is - use curve.area to read, if not, use COM. However, do not use COM in overrules! In that case you can't tell area.
The way to go would be to try to see if GECURVE can bring some area.

Here is the code to check if .NET API is good for read. I HAVE NOT TESTED THIS ALL TROUGH!
Code - vb.net: [Select]
  1. Public Shared Function isAreaOK(testcurve As Curve) As Boolean
  2.             'if curve intersect with itself, including imaginary start to end line, then its reporterd area is wrong
  3.             If testcurve.GetRXClass.IsDerivedFrom(xlineType) Then Return False
  4.             Dim selfintersection As Integer = 0
  5.             Dim cge As Curve3d = testcurve.GetGeCurve
  6.             Dim ci As New CurveCurveIntersector3d(cge, cge, testcurve.GetPlane.Normal)
  7.             selfintersection = ci.NumberOfIntersectionPoints
  8.             Dim overlapcnt As Integer = ci.OverlapCount
  9.             Dim startendintersections As Integer = 2
  10.             If testcurve.StartPoint <> testcurve.EndPoint Then
  11.                 Dim cconect As New Line(testcurve.StartPoint, testcurve.EndPoint)
  12.                 Dim cgconnect As Curve3d = cconect.GetGeCurve
  13.                 Dim cstartend As New CurveCurveIntersector3d(cge, cgconnect, testcurve.GetPlane.Normal)
  14.                 startendintersections = cstartend.NumberOfIntersectionPoints
  15.  
  16.                 cconect.Dispose()
  17.                 cgconnect.Dispose()
  18.                 cstartend.Dispose()
  19.  
  20.             End If
  21.  
  22.             cge.Dispose()
  23.             ci.Dispose()
  24.  
  25.             'sits on itself partialy
  26.             If overlapcnt > 0 Then Return False
  27.  
  28.             If startendintersections = 2 Or startendintersections = 0 Then
  29.                 '0 = single line, single vertice
  30.                 '2 = non self-intersecting polyline with 2 or more vertices, and imaginary line connects startpoint and endpoint
  31.                 If selfintersection = 0 Then Return True
  32.             End If
  33.             Return False
  34.  
  35.         End Function

concerns:
-disposing?
-is startpoint=endpoint comparing doubles? if so, this may also be unpredictable test
-3d?
EDIT: sorry, I had declared xline somewhere else Public Shared xlineType = RXClass.GetClass(GetType(Xline))
« Last Edit: December 22, 2014, 10:47:25 AM by nekitip »

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: polyline area
« Reply #18 on: December 22, 2014, 01:16:44 PM »
Why can we not use COM in overrules?

What about converting closed polyline to region and using its area property?
Revit 2019, AMEP 2019 64bit Win 10

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: polyline area
« Reply #19 on: December 22, 2014, 02:24:45 PM »
FYI, this is the response I got from Autodesk's DevHelp regarding the Curve.Area property:
Quote from: ADN
The reason for this difference is due to the way the curve area is computed as compared to the AREA command. A curve's area is computed by integration over the curve. In an intersecting polyline, one of the loop is clockwise and the other is counter-clockwise and due to the sign the area is the difference of the loop areas.


To compute the polyline area just as the AREA command in AutoCAD does, it is required to consider the intersection points of the polyline and compute the area of the loops separately and sum them. The value that you see in AutoCAD's property palette and the value from the COM API both use this method.


To determine if the polyline is self-intersecting, you will find this blog post helpful :

http://adndevblog.typepad.com/autocad/2012/05/how-to-detect-if-a-polyline-is-self-intersecting.html

nekitip

  • Guest
Re: polyline area
« Reply #20 on: December 22, 2014, 03:33:19 PM »
Why can we not use COM in overrules?
If you can, than I'm doing something wrong.

nekitip

  • Guest
Re: polyline area
« Reply #21 on: December 22, 2014, 03:40:06 PM »
FYI, this is the response I got from Autodesk's DevHelp regarding the Curve.Area property:
Quote from: ADN
The reason for this difference is due to the way the curve area is computed as compared to the AREA command. A curve's area is computed by integration over the curve. In an intersecting polyline, one of the loop is clockwise and the other is counter-clockwise and due to the sign the area is the difference of the loop areas.


To compute the polyline area just as the AREA command in AutoCAD does, it is required to consider the intersection points of the polyline and compute the area of the loops separately and sum them. The value that you see in AutoCAD's property palette and the value from the COM API both use this method.


To determine if the polyline is self-intersecting, you will find this blog post helpful :

http://adndevblog.typepad.com/autocad/2012/05/how-to-detect-if-a-polyline-is-self-intersecting.html
As I have said in a few posts before, both this anwser and this blog (as referenced in my earlier code) is incomplete. This is problem of AutoCAD, nothing is ever complete, and always blog blog blog... never documentation.

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: polyline area
« Reply #22 on: December 23, 2014, 08:22:10 AM »
Why can we not use COM in overrules?
If you can, than I'm doing something wrong.


I had never tried using COM inside an overrule before.  I avoid COM unless there is no other alternative. So after some experimenting you're right about ObjectOverrules. I can't get it to work no matter how I attempt to use it inside an ObjectOverrule. DrawableOverrules and GripOverrules seem to handle COM just fine though. I was able to get properties inside both WorldDraw and GetGripPoints methods.
Revit 2019, AMEP 2019 64bit Win 10

nekitip

  • Guest
Re: polyline area
« Reply #23 on: December 23, 2014, 09:04:11 AM »
I'm kind of feeling that reading COM also modifies object in some way. Like entity has some quantum state you disturb just by reading it :)
I haven't try i worlddraw since COM is slow.

Has anyone looked into my isareaOK routine? This may look like promising way to go, but I have my concens about both routine (disposing, 3d, elevations, vieports...), and also - will it work in all cases. Since, half good is no good.