HI , im fairly new to using the API documentation and im having some trouble creating a VBA macro that allows me to use this :
Public Sub DivideByPlane(_val As double, _axis As IRobotGeoCoordinateAxis, Optional _only_gen_node As Boolean = false)
my purpose here is to be able to divide for exemple my already open robot model that is composed of 5 bars , 1to5
by plane z=3 for exemple .
and i would like to use the divideByplane function if possible .
As i said , ive been trying to make sense of the documentation about this function and how to properly make it work on vba , but its not that easy for someone not used to it .
can anyone show me an exemple of how it can be done ?.
Thanks in advance for your help and guidance.
Solved! Go to Solution.
Solved by youssef_taamallahCZ4NM. Go to Solution.
Solved by Stephane.kapetanovic. Go to Solution.
there is no API function to use directly for this. What you are looking for is the intersection of two lines in 2d geometry. For the numbers of the nodes and their coordinates XZ, the API can provide them to you. To code the function, there are many examples on the web, it also seems to me that your cutting line is horizontal, you will only have to make a proportion.
Best Regards
Thank you for your answer, as i have been on a long vacation i couldnt answer this before .
I was reffering to this function that is described in the API documentation in page 754 .
As you can see in the picture below :
somehow i cant make it work in VBA ,
Are you sure there isnt a way to make use of this ?
Thanks again for your input on the subject .
DivideBar already exist from IRobotStructureEditTools on page 1038, your case is to find intesection with the plane (a line in 2D), for that nothing exist apart 2D/3D trigonometry, you have to make your own.
Best Regards
Example of 2D function
Function Intersection(p1 As Point, p2 As Point, p3 As Point, p4 As Point) As Point
Dim a1 As Double, a2 As Double, b1 As Double, b2 As Double
Dim c1 As Double, c2 As Double, d As Double
a1 = p2.y - p1.y: b1 = p1.x - p2.x: c1 = a1 * p1.x + b1 * p1.y
a2 = p4.y - p3.y: b2 = p3.x - p4.x: c2 = a2 * p3.x + b2 * p3.y
d = a1 * b2 - a2 * b1
If d = 0 Then
MsgBox "The lines are parallel and do not intersect.": Exit Function
End If
With Intersection
.x = (b2 * c1 - b1 * c2) / d
.y = (a1 * c2 - a2 * c1) / d
End With
End Function
Note : you can suppress the message (lines 9 to 11) if you make the input data reliable
To use DivideBar here an example
Sub DivideBarByPlane2D(p1 As Point, p2 As Point)
Dim RobApp As RobotApplication, Visible As Boolean, IsActive As Boolean
Set RobApp = New RobotApplication
Visible = RobApp.Visible = -1
IsActive = RobApp.Project.IsActive = -1
If Not (Visible And IsActive) Then
Set RobApp = Nothing: Exit Sub
End If
Dim BarCol As IRobotCollection
Dim Nodes As RobotNodeServer, Bars As RobotBarServer, Bar As RobotBar
Dim EditTools As IRobotStructureEditTools, RVA As RobotValuesArray
Dim p3 As Point, p4 As Point, Length As Double, a As Double, b As Double
With RobApp.Project.Structure
Set Bars = .Bars
Set Nodes = .Nodes
Set EditTools = .Edit
Set BarCol = Bars.GetMany(.Selections.Get(I_OT_BAR))
End With
Set RVA = New RobotValuesArray: RVA.SetSize 1
For i = 1 To BarCol.Count
Set Bar = BarCol.Get(i)
With Nodes
With .Get(Bar.StartNode): p3.x = .x: p3.y = .z: End With
With .Get(Bar.EndNode): p4.x = .x: p4.y = .z: End With
End With
Length = Bar.Length
With Intersection(p1, p2, p3, p4)
a = d2D(.x - p3.x, .y - p3.y)
b = d2D(.x - p4.x, .y - p4.y)
End With
If Abs(a + b - Length) < TolE Then
RVA.Set 1, a / Length
Set BarNos = EditTools.DivideBar(Bar.Number, RVA, True)
End If
Next i
Set RobApp = Nothing
End Sub
Before
After
Mentioned function is designed for panel \ contour edges only.
Use approach given by @Stephane.kapetanovic above.
@Stephane.kapetanovic Thank you for the tip , i will need to figure something out to make this work for 3D objects .
But ill make it work 🙂
I will keep you updated with the final solution once i make it happen .
much thanks !
Hi @Stephane.kapetanovic i was able to get some heavy inspiration from your exemple in order to make it work on 3D .
i have made slight adjustments to the intersection function and i made it work automatically on all selected bars .
Public Const TolE = 0.0001
Type Point
x As Double
y As Double
z As Double
End Type
Private Function Intersection(zp As Double, p3 As Point, p4 As Point) As Point
Dim Alpha As Double, Beta As Double
Alpha = (p4.x - p3.x) / (p4.z - p3.z)
Beta = (p4.y - p3.y) / (p4.z - p3.z)
With Intersection
.x = ((Alpha) * (zp - p3.z)) + p3.x
.y = ((Beta) * (zp - p3.z)) + p3.y
.z = zp
End With
End Function
Sub DivideBarByPlane3D(zp As Double)
' Déclaration et initialisation d'une nouvelle instance de l'application Robot Structural Analysis
Dim RobApp As RobotApplication, Visible As Boolean, IsActive As Boolean
Set RobApp = New RobotApplication
' Vérifie si l'application est visible et active
Visible = RobApp.Visible = -1
IsActive = RobApp.Project.IsActive = -1
' Si l'application n'est pas visible ou active, sortir de la subroutine
If Not (Visible And IsActive) Then
Set RobApp = Nothing: Exit Sub
End If
' Déclaration des variables pour stocker la collection de barres, les nœuds, les outils d'édition de la structure et les valeurs numériques
Dim BarCol As IRobotCollection
Dim Nodes As RobotNodeServer, Bars As RobotBarServer, Bar As RobotBar
Dim EditTools As IRobotStructureEditTools, RVA As RobotValuesArray
Dim p3 As Point, p4 As Point, Length As Double, a As Double, b As Double
' Récupération des barres sélectionnées et des nœuds de départ et d'arrivée de chaque barre
With RobApp.Project.Structure
Set Bars = .Bars
Set Nodes = .Nodes
Set EditTools = .Edit
Set BarCol = RobApp.Project.Structure.Bars.GetAll()
End With
' Création d'une nouvelle instance de RobotValuesArray pour stocker les valeurs numériques
Set RVA = New RobotValuesArray: RVA.SetSize 1
' Boucle pour parcourir chaque barre sélectionnée
For I = 1 To BarCol.Count
' Récupération de la barre et de ses nœuds de départ et d'arrivée
Set Bar = BarCol.Get(I)
With Nodes
With .Get(Bar.StartNode): p3.x = .x: p3.y = .y: p3.z = .z: End With
With .Get(Bar.EndNode): p4.x = .x: p4.y = .y: p4.z = .z: End With
End With
' Calcul de la longueur de la barre et de la distance entre les points d'intersection et les nœuds de départ et d'arrivée
Length = Bar.Length
With Intersection(zp, p3, p4)
a = d3D(.x - p3.x, .y - p3.y, .z - p3.z)
b = d3D(.x - p4.x, .y - p4.y, .z - p4.z)
End With
' Si la somme de a et b est égale à la longueur de la barre dans une certaine tolérance, diviser la barre en deux parties égales
If Abs(a + b - Length) < TolE Then
RVA.Set 1, a / Length
Set BarNos = EditTools.DivideBar(Bar.Number, RVA, True)
End If
Next I
' Fermeture de l'instance de l'application Robot Structural Analysis
Set RobApp = Nothing
End Sub
Function d3D(x As Double, y As Double, z As Double) As Double
d3D = Sqr(x * x + y * y + z * z)
End Function
Sub Divide()
Dim n As Integer
n = Range("C" & 5)
For I = 6 To 6 + n - 1
Dim zp As Double
' Example with a cut // to z at level zp
' Select Bars and run
' Program cuts each selected bar
zp = Range("D" & I)
DivideBarByPlane3D zp
Next I
MsgBox " Divisions realisée ! , veuillez vérifier la coherence des résultats"
End Sub
i also made it work for multiple instances of zp so i could repeat the division n times , as much as needed :
this here is the list of heights at which i want to divide my bars .
This is before :
This is before :
So yeah ... even if it took a while to get , i was able to make this work .
This is really usefull to design or make divides on many levels at a time for pylones .
I dont know if this code can be simplified , but it works fine 🙂
Thank you again for the help and advices .
Best regards
Can't find what you're looking for? Ask the community or share your knowledge.