Home Image-Pro Automation (Macros, Apps, Reports)

MEASUREMENTS from BEST FIT ARC . . .

2021-06-01-114853

All --

I would like to add a BEST FIT ARC TOOL to a project that I am working on.

In this application, the USER would create the BEST FIT ARC using 4 points.

In the SCREEN CAPTURE below, the BEST FIT ARC (BFA1) follows the CIRCLE.

For this project, the IMAGE-PRO CODE needs to create a NEW ARC (BFA2) that has

    BFA2 CENTER = BFA1 CENTER

and

    BFA2 RADIUS = BFA1 RADIUS - OFFSET

After doing an ADD ALL in the AVAILABLE MEASUREMENTS, BFA1 generates the following measurements.


The TIF IMAGE with BFA1 overlaid on the IMAGE is attached as

    2021-06-01-114125.tif

When I record a MACRO and create a BEST FIT ARC, the code below is generated.

    Public Function NewMacro3() As SimpleScript
        NewMacro3 = New SimpleScript
        Dim doc1, meas1

        With Application.DocumentCommands.Active(NewMacro3)
            .Run(doc1)
        End With

        With Measure.MeasurementsCommands.Options(NewMacro3)
            .NMaxPointsArcs = 4
            .Run(doc1)
        End With

        With Measure.MeasurementsCommands.Add(NewMacro3)
            .MeasurementType = McMeasurements.enumMMSTypes.mmtsBestFitArc
            .Points = New System.Collections.Generic.List(Of System.Drawing.PointF)
            .Points.Add(New System.Drawing.PointF(89.73759F,251.2154F))
            .Points.Add(New System.Drawing.PointF(117.1162F,298.7089F))
            .Points.Add(New System.Drawing.PointF(333.9099F,265.7428F))
            .Points.Add(New System.Drawing.PointF(345.6436F,217.6906F))
            .FeatureName = "BFA2"
            .SnapFeature = False
            .Run(doc1, meas1)
        End With

    End Function

Knowing the BFA1 CENTER, I can find 4 points that are OFFSET from the original BFA1 POINTS along lines from the POINTS to the CENTER.  This is a bit of a headache but I know it can be done and then these points can be used to create BFA2.

Is there a better way to achieve a BFA2 that is CONCENTRIC with BFA1 but with a RADIUS that is reduced by an OFFSET?

Thanks.

-- Matt

-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*



Answers

  • edited June 2021
    Hi Matt,

    So, you want to draw a new arc with the same center, start and end angle, but different radius, right?

    In that case you should use Arc Center X/Y, Arc Angle, Arc Radius, Start X/Y (or End X/Y) measurements of the original arc and calculate coordinates of arc points with the new radius for the given angle range. You can calculate coordinates of 3 points of the arc (Start, Middle, End) and create the new Arc (mmtsBestFitArc) or you can draw a Polyline (mmtsPolygonalLine) using more points of arc coordinates. 

    Yuri
  • 2021-06-02-094510

    Yuri --

    Yes.

    I would like BFA2 to be CONCENTRIC with BFA1 with a different RADIUS.

    If possible, I would like the ARC START POINTS to lie on the same LINE to the CENTER and the ARC END POINTS to lie on the same LINE to the CENTER.

    I have attempted to show this below.





    Is there some elegant way to make this happen using the BFA1 MEASUREMENTS to feed the creation of BFA2 with just a modification of the RADIUS?

    Thanks.

    -- Matt

  • edited June 2021
    Hi Matt,

    There is no special function that would create an arc with modified radius, you should do all the calculations yourself based on the parameters I mentioned in the previous post.
    x = xc + radius * cos(angle)  
    y = yc + radius * sin(angle)

    Yuri
  • 2021-06-02-143443

    Yuri --

    While working on this I tried to access the MEASUREMENTS of FEATURES but could not find the right

    McMMSubFeature. mcmmsfTypes Enumeration

    for the BEST FIT ARC.

    When all I have in the image is BEST FIT ARCs, the following CODE

            'Connect with the data for this image count
            Dim MyData As McMMData
            With measure.MeasurementsCommands.GetData(Nothing)
                .Run(docAA, MyData)
            End With
    
            'Loop through the features found in the current image document
    
            Dim MyBfaCount As Integer = _
                0
    
            Dim MyI As Integer
    
            For MyI = 0 To MyData.Rows-1
    
    '                If ( _
    '                    MyData.SubFeature(MyI).FeatureType = _
    '                        McMMSubFeature.mcmmsfTypes.mcmmsfBestFit _
    '                    ) _
    '                    Then
    '
    '                        MyBfaCount = _
    '                            MyBfaCount + 1
    '
    '                        Debug.Print "MyBfaCount"
    '                        Debug.Print MyBfaCount
    '
    '                    End If
    
                    Debug.Print "MyData.SubFeature(MyI).FeatureType"
                    Debug.Print MyData.SubFeature(MyI).FeatureType
    
                Next

    Generates

    MyData.SubFeature(MyI).FeatureType
    26
    MyData.SubFeature(MyI).FeatureType
    26
    MyData.SubFeature(MyI).FeatureType
    26
    MyData.SubFeature(MyI).FeatureType
    26

    Is there a modification to the code below that would pick up on BEST FIT ARCs?

    '                If ( _
    '                    MyData.SubFeature(MyI).FeatureType = _
    '                        McMMSubFeature.mcmmsfTypes.mcmmsfBestFit _
    '                    ) _
    

    Is there a more elegant way to check if a FEATURE is a BEST FIT ARC than seeing if its

        FEATURE TYPE = 26

    Thanks.

    -- Matt



  • 2021-06-02-183024

    Yuri --

    I am having trouble getting this to work properly.

    I have created a routine

        ShiftBFA

    which is attached in

        ShiftBFA.txt

    This routine has issues that I think are related to the quadrant of the area around the center where:

    -- UPPER RIGHT = + X , - Y
    -- UPPER LEFT = - X, - Y
    -- LOWER LEFT = -X, + Y
    -- LOWER RIGHT = + X, + Y

    I then started looking at the ANGLES that are listed as FEATURE MEASUREMENTS and I cannot make them make sense either.  Here is an image that shows what I mean.



    I cannot figure out what about BFA1 has an ANGLE of 123 or 74.  27 might be the ANGLE from START to FINISH.

    The IMAGE shown in the example immediately above is attached as

        2021-06-02-154610.tif

    Can you please give me some guidance on the best way to make a BFA2 which is .1 UNITS toward the center of BFA1?

    Thanks.

    -- Matt

  • edited June 2021
    Hi Matt,

    You have to use Start X/Y and End X/Y coordinates to calculate start and end Angle of the arc.

    The easiest way to calculate the angle is by using atan2 function:
    angle = System.Math.atan2(y - cy, x - cx)
    where x and y are Start X/Y or End X/Y and cx/cy are center coordinates.

    Note that all Math functions handle angles in radians.

    Here is the page with detailed explanation:
    https://stackoverflow.com/questions/46387747/find-angle-of-point-on-circle

    Let me know if it works for you.

    Yuri
  • 2021-06-03-085810

    Yuri --

    Thanks you for the guidance.

    I will look at this ASAP.

    Would you mind sending me some CODE (if it can be done) that extracts the POINTS that are the END POINTS for the SEGMENTS along the BEST FIT ARC?

    Using them and the CENTER will be a PLAN B if I cannot get PLAN A operational.

    Thanks again.

    -- Matt


  • Hi Matt,

    Start X/Y and End X/Y are the measurements of the arc:


    you can get them the same way as Arc Center X/Y.

    Yuri
  • edited June 2021
    2021-06-03-092646

    Yuri --

    I am sorry.

    The points I am referring to ( for PLAN B ) are the ones shown with the WHITE SQUARES in the image below.

    Is there CODE that will give me access to their coordinates?

    Thanks.

    -- Matt




  • 2021-06-03-100004

    Yuri --

    Below is an image that captures the functionality when I attempt to get the COORDINATES for a CONCENTRIC BEST FIT ARC using the code I sent yesterday. 

    There seems to be an issue with the MID POINT generated by the location of the CENTER.

    There are also issues when the ARC is not all in one quadrant.






    Thanks.

    -- Matt
  • Hi Matt,

    Here is the post that explains how to get point coordinates of any feature: https://forums.mediacy.com/discussion/comment/543/

        Public Sub PrintOutlineCoordinates
            Dim im As McImage=ThisApplication.ActiveImage
            If im Is Nothing Then Exit Sub'no image
            Dim md As McMMData=im.MeasurementsData
            ThisApplication.Output.Show
            For Each sf As McMMSubFeature In md.SubFeatures
                Dim s As String=sf.Name
                Dim points() As SINGLEPOINT=Nothing
                sf.GetFeatures.GetFeaturePoints(sf.FeatureIndex,points)
                For Each p As SINGLEPOINT In points
                    s+=" {" & p.x.ToString("F2") & "," & p.y.ToString("F2") & "}"
                Next
                ThisApplication.Output.PrintMessage(s)
            Next
        End Sub

    You can use it for an Arc as well.

    Yuri
  • 2021-06-03-105328

    Yuri --

    Super.

    I remembered that there had been projects handled before that needed the points but I got it in my head that pulling them out of a BEST FIT ARC would be different.

    Thank you for clarifying the method for pulling the points from a BFA and providing example CODE.

    Much appreciated.

    -- Matt

  • 2021-06-03-155026

    Yuri --

    Thank you again for your assistance.

    I have got the CODE working to COLLECT the BEFORE POINTS on the BEST FIT ARC and then plot the points for the AFTER POINTS 1/2 between the BEFORE ARC and the CENTER.

    This is shown in the IMAGE BELOW and performed by the CODE BELOW.

    I am working to modify this so that the OFFSET is based on a SET OFFSET.

    Thanks again.

    -- Matt




        Public Sub ShiftBFA3()
    
            'CONNECT WITH THE ACTIVE IMAGE
            Dim im2 As McImage=ThisApplication.ActiveImage
    
            'ERROR TRAP FOR NO IMAGE
            If im2 Is Nothing Then Exit Sub
    
            'SHOW THE OUTPUT WINDOW
            ThisApplication.Output.Show
    
            'CONNECT WITH THE MEASUREMENTS IN THE ACTIVE IMAGE
            Dim md2 As McMMData=im2.MeasurementsData
    
            'LOOP THROUGH THE FEATURES IN THE ACTIVE IMAGE
            For Each sf As McMMSubFeature In md2.SubFeatures
    
                If ( _
                    sf.FeatureType = _
                        26 _
                    ) _
                    Then
    
                        'LEARN THE NAME FOR THE ACTIVE FEATURE
    
                        Dim s As String
    
                        s = _
                            "Name = " & vbLf & _
                            sf.Name
    
                        ThisApplication.Output.PrintMessage(s)
    
                        'LEARN THE CENTER FOR THE ACTIVE FEATURE
    
                        s = _
                            "CENTER = " & vbLf & _
                            " {" & sf.Value(eMeasures.LnBestFitArcCenterX).ToString("F2") & "," & sf.Value(eMeasures.LnBestFitArcCenterY).ToString("F2") & "}"
    
                        ThisApplication.Output.PrintMessage(s)
    
                        Dim image1, meas1
    
                        With Application.DocumentCommands.ActiveImage(Nothing)
                            .Run(image1)
                        End With
    
                        With Measure.MeasurementsCommands.Add(Nothing)
                            .MeasurementType = McMeasurements.enumMMSTypes.mmtsManualTag
                            .Points = New System.Collections.Generic.List(Of System.Drawing.PointF)
                            .Points.Add _
                                ( _
                                New System.Drawing.PointF( _
                                    sf.Value(eMeasures.LnBestFitArcCenterX)  / ThisApplication.ActiveImage.SpatialCalibration.PixelSizeX, _
                                    sf.Value(eMeasures.LnBestFitArcCenterY)  / ThisApplication.ActiveImage.SpatialCalibration.PixelSizeY) _
                                )
                            .FeatureName = "CENTER"
                            .SnapFeature = False
                            .Run(image1, meas1)
                        End With
    
                        s = _
                            "POINTS = "
    
                        ThisApplication.Output.PrintMessage(s)
    
                        'LEARN THE POINTS IN THE ACTIVE FEATURE
                        Dim points() As SINGLEPOINT = _
                            Nothing
                        sf.GetFeatures.GetFeaturePoints(sf.FeatureIndex,points)
    
                        'LOOP THROUG THE POINTS IN THE ACTIVE FEATURE
                        Dim MyI As Integer = _
                            0
                        For Each p As SINGLEPOINT In points
    
                                MyI += _
                                    1
    
                                s= _
                                    " {" & p.x.ToString("F2") & "," & p.y.ToString("F2") & "}"
    
                                ThisApplication.Output.PrintMessage(s)
    
    '                            Dim image1, meas1
    '
    '                            With Application.DocumentCommands.ActiveImage(Nothing)
    '                                .Run(image1)
    '                            End With
    
                                With Measure.MeasurementsCommands.Add(Nothing)
                                    .MeasurementType = McMeasurements.enumMMSTypes.mmtsManualTag
                                    .Points = New System.Collections.Generic.List(Of System.Drawing.PointF)
                                    .Points.Add _
                                        ( _
                                        New System.Drawing.PointF( _
                                            p.x , _
                                            p.y ) _
                                        )
                                    .FeatureName = "B" & Format(MyI,"00")
                                    .SnapFeature = False
                                    .Run(image1, meas1)
                                End With
    
                                'CALCULATE THE AFTER X AND AFTER Y
                                Dim After As SINGLEPOINT
    
                                After.x = _
                                    ( _
                                    sf.Value(eMeasures.LnBestFitArcCenterX)  / ThisApplication.ActiveImage.SpatialCalibration.PixelSizeX +
                                    p.x _
                                    ) / 2.
    
                                After.y = _
                                    ( _
                                    sf.Value(eMeasures.LnBestFitArcCentery)  / ThisApplication.ActiveImage.SpatialCalibration.PixelSizeY +
                                    p.y _
                                    ) / 2.
    
                                With Measure.MeasurementsCommands.Add(Nothing)
                                    .MeasurementType = McMeasurements.enumMMSTypes.mmtsManualTag
                                    .Points = New System.Collections.Generic.List(Of System.Drawing.PointF)
                                    .Points.Add _
                                        ( _
                                        New System.Drawing.PointF( _
                                            After.x , _
                                            After.y ) _
                                        )
                                    .FeatureName = "A" & Format(MyI,"00")
                                    .SnapFeature = False
                                    .Run(image1, meas1)
                                End With
    
                            Next
    
                    End If
    
                Next
    
            md2.BeginUpdateBlock(False)
    
        End Sub
    
    





Sign In or Register to comment.