This solidworks vba macro will draw a one pixel wide circle over top of every non white pixel that is right next to a white pixel. You'll have to adjust lines 36 and 40 of the macro before it will work for you. Line 36 points solidworks to your default part file. And line 40 points solidworks to the file location of the image you want to process. This macro works by creating a part file, inserting a sketch on the front plane, then inserting a sketch image. The pixel comparison works by reading the color data from every pixel in the image and loading those pieces of data into an array of numbers. The data values represent the amount of RGB (red green blue) each pixel has. The 3 array values that represent each pixel are added together and compared to the four pixels that surround it. RGB values range from 0 to 255. A purely white pixel will have an R value of 255, G value of 255 and B value of 255. A completely black pixel has RGB values of 0,0,0. Return to the SolidWorks VBA Macros page.

edgeDetect.bmp
edgeDetect.swp

  1.  
  2. 'Pre-conditions: Adjust line 36 of the macro to point to your default solidworks part file
  3. 'Prec-onditions: Adjust line 40 to point to an image file that contains white and non white pixels
  4. 'Purpose: This macro draws a circle over every non white pixel that borders a white pixel
  5. 'Result: Every edge pixel will have a circle drawn on it'
  6. 'Result: An array is populated with the X and Y locations of every edge pixel for future development'
  7.  
  8. Option Explicit
  9. Dim swApp As SldWorks.SldWorks
  10. Public swModel As SldWorks.ModelDoc2
  11. Dim swFeat As SldWorks.Feature
  12. Dim swSketchPicture As SldWorks.ISketchPicture
  13. Dim swSelMgr As SldWorks.SelectionMgr
  14. Dim boolstatus As Boolean
  15. Public w As Long
  16. Public h As Long
  17. Public width As Double
  18. Public height As Double
  19. Dim xx As Double
  20. Dim yy As Double
  21. Public i As Long
  22. Public j As Long
  23. Public RGBs
  24. Public pixels
  25. Public rgbArray() As Integer
  26. Public k As Long
  27. Public xPos As Integer
  28. Public yPos As Double
  29. Public skSegment As Object
  30. Public d As Long
  31. Dim myArray() As Double
  32. Public white As Boolean
  33.  
  34. Sub main()
  35. Set swApp = Application.SldWorks
  36. Set swModel = swApp.NewDocument("C:\ProgramData\SolidWorks\SOLIDWORKS 2017\templates\Part.prtdot", 0, 0, 0) 'This line opens up SolidWorks default part document. If you do not have SW 2017, or you have installed SolidWorks to a different location, this line will need to be changed.'
  37. Set swModel = swApp.ActiveDoc
  38. Set swSelMgr = swModel.SelectionManager
  39. swModel.SketchManager.InsertSketch True
  40. Set swSketchPicture = swModel.SketchManager.InsertSketchPicture("C:\Users\Atom\Pictures\p.jpg")
  41. swModel.SketchManager.InsertSketch True
  42. boolstatus = swModel.Extension.SelectByID2("Sketch1", "SKETCH", 0, 0, 0, False, 0, Nothing, 0)
  43. swModel.EditSketch
  44. boolstatus = swModel.Extension.SelectByID2("Sketch Picture1", "SKETCHBITMAP", 0, 0, 0, False, 0, Nothing, 0)
  45. Set swFeat = swSelMgr.GetSelectedObject6(1, -1)
  46. swSketchPicture.GetOrigin xx, yy
  47. swSketchPicture.GetSize width, height
  48. RGBs = swSketchPicture.GetPixelmapSize(w, h)
  49. pixels = RGBs / 3
  50. rgbArray = swSketchPicture.GetPixelmap() 'this is an array with every rgb value of the image, starting in the upper left and ending lower right'
  51. drawLine
  52. End Sub
  53.  
  54. Sub drawLine()
  55. Dim instance As ISketchManager
  56. Set instance = swModel.SketchManager
  57. instance.AddToDB = True
  58. d = 0
  59. j = 0
  60. For i = 0 To pixels
  61. white = False
  62. If (d + 3 * w) < RGBs Then
  63. If (rgbArray(d + 3 * w) + rgbArray(d + 1 + 3 * w) + rgbArray(d + 2 + 3 * w) > 750) Then 'if pixel below is white'
  64. white = True
  65. End If
  66. End If
  67. If white = False And d > 2 + 3 * w Then
  68. If rgbArray(d - 3 * w) + rgbArray(d + 1 - 3 * w) + rgbArray(d + 2 - 3 * w) > 750 Then 'if pixel above is white'
  69. white = True
  70. End If
  71. End If
  72. If white = False And d > 0 Then
  73. If rgbArray(d - 3) + rgbArray(d - 2) + rgbArray(d - 1) > 750 Then 'if pixel to the left is white'
  74. white = True
  75. End If
  76. End If
  77. If white = False And d < RGBs - 3 Then
  78. If rgbArray(d + 3) + rgbArray(d + 4) + rgbArray(d + 5) > 750 Then 'if pixel to the right is white'
  79. white = True
  80. End If
  81. End If
  82.  
  83. If d / 3 < pixels Then
  84. If (rgbArray(d) + rgbArray(d + 1) + rgbArray(d + 2) < 761 And white) Then
  85. If isFar(j, (d / 3 Mod w) / w * width + 0.5 * width / w, height - Int(d / 3 / w) / h * height - 0.5 * height / h) Then
  86. myArray(0, j) = (d / 3 Mod w) / w * width + 0.5 * width / w 'X value'
  87. myArray(1, j) = height - Int(d / 3 / w) / h * height - 0.5 * height / h 'Y value'
  88. Set skSegment = swModel.SketchManager.CreateCircle(myArray(0, j), myArray(1, j), 0#, myArray(0, j), myArray(1, j) + height / h * 0.5, 0#)
  89. j = j + 1
  90. End If
  91. End If
  92. End If
  93. d = d + 3
  94. Next i
  95. instance.AddToDB = False
  96. End Sub
  97.  
  98. Public Function isFar(arrayElement As Long, xPos As Double, yPos As Double) As Boolean
  99. isFar = True
  100. If arrayElement = 0 Then
  101. ReDim Preserve myArray(1, arrayElement)
  102. myArray(0, arrayElement) = xPos
  103. myArray(1, arrayElement) = yPos
  104. Exit Function
  105. End If
  106.  
  107. For k = arrayElement To 1 Step -1 'here we make sure the current pixel woot s location is at least 1 pixel length from all other edge pixels'
  108. If (xPos - myArray(0, k - 1)) ^ 2 + (yPos - myArray(1, k - 1)) ^ 2 < (height / h) ^ 2 - 0.00000254 Then
  109. 'If (xPos - myArray(0, k - 1)) ^ 2 + (yPos - myArray(1, k - 1)) ^ 2 < (height / h + height / h) ^ 2 - 0.00000254 Then'
  110. isFar = False
  111. Exit Function
  112. End If
  113. Next k
  114. ReDim Preserve myArray(1, arrayElement) 'only the last dimension of an array can be redimensioned'
  115. myArray(0, arrayElement) = xPos
  116. myArray(1, arrayElement) = yPos
  117. End Function
  118.  

      If you comment out line 108 with an apostrophe and uncomment line 109 each edge pixel must be 2 pixel lengths apart to have a circle drawn over top of it or to be added to the array of edge pixels. Your result should look like the following image:



Notes:


SolidWorks macros must be written with meters not inches. 1 meter equals .0254 inches.

Because of snapping, most circles would not draw properly while this macro ran. This is no longer a problem. The solution to this issue is found on or around line 57 of the main code: part.SketchManager.AddToDB = True This line of code bypasses the snapping portion of the drawing process. Line 95 returns the value to False although without line 95 I've never had a problem.

Line 77 of the macro populates an array with every rgb value in your image. For instance rgbArray(0) is the red value of the first pixel which is in the upper left corner of the image. rgbArray(1) is the green value of the first pixel. and rgbArray(2) is the blue value for pixel 1. The order of pixels in the array is left to right, top to bottom. So the last pixel value in the array is the blue value of the lower right hand corner's pixel.

Only the last dimension of an array in VBA can be redimensioned if you want to Preserve the original data in the array. For this reason the macro populates the array myArray in a strange way on line 101. The first dimension always only has 2 elements 0 and 1 but the 2nd dimension becomes larger every time a pixel meets the isFar functions criteria for being True.

The VBA logical operator AND causes the 2nd boolean expression to be evaluated even if the first boolean expression evaluates to false. For this reason I use nested if-then statements instead of the AND operator. With thousands or tens of thousands of pixels to be evaluated this can shave seconds off execution time.