Collecting vertexes/points to pass to a bspline function

Post here for help on using FreeCAD's graphical user interface (GUI).
Forum rules
and Helpful information
IMPORTANT: Please click here and read this first, before asking for help

Also, be nice to others! Read the FreeCAD code of conduct!
Post Reply
mconsidine
Posts: 125
Joined: Wed Jan 18, 2023 10:41 pm
Location: Randolph, VT USA

Collecting vertexes/points to pass to a bspline function

Post by mconsidine »

Hi,
This is a follow-on to the question posted in this thread:
https://forum.freecadweb.org/viewtopic.php?f=3&t=75508

Firstly:

Code: Select all

OS: Linux Mint 21 (X-Cinnamon/cinnamon)
Word size of FreeCAD: 64-bit
Version: 0.21.0.31700 (Git)
Build type: Unknown
Branch: master
Hash: 0a8ea55509c2a03c18ec7d95100b765c59b19560
Python 3.10.6, Qt 5.15.3, Coin 4.0.1, Vtk 9.1.0, OCC 7.5.1
Locale: English/United States (en_US)
Installed mods: 
  * toSketch 1.0.1
I have a minimal example attached, along with a test macro that shows my efforts so far. To use the macro, load the test case, select the 4 sketches and then run the macro. A 5th sketch will be created showing the intersection of the sketches with a plane, with shapes identifying the respective intersections. E.g.:
Screenshot from 2023-01-29 17-17-14.png
Screenshot from 2023-01-29 17-17-14.png (2.36 KiB) Viewed 743 times
My end goal is to use the endpoints on the generated cross-sections as inputs to a bspline. I can manually edit the sketch, identify a couple of points and select the spline feature in Sketcher. I can then extrude it in each direction along the edge going in the Y-direction of the bottom-most sketch/shape.

But I would like to do this programmatically (as I also can't seem to figure out how to lock the endpoints but move around the control points on the bezier). As can be seen in the created sketch ("cs_plane_sketch") I have objects with endpoints. But for the life of me I can't find an example of how to collect, say, all the ones with positive X-values and feed them to a Bspline routine. I thought the topic on Bsplines and point clouds
https://forum.freecadweb.org/viewtopic. ... 66#p656266
would get me there, but I can't figure out how to get these endpoints to be, well, Points.

Can anyone point me to a tutorial or approach that will get me going?

TIA,
mconsidine
Attachments
test.FCMacro
(2.29 KiB) Downloaded 8 times
b_test.FCStd
(11.8 KiB) Downloaded 8 times
keithsloan52
Veteran
Posts: 2756
Joined: Mon Feb 27, 2012 5:31 pm

Re: Collecting vertexes/points to pass to a bspline function

Post by keithsloan52 »

You are selecting a number of the horizontal sketch lines? Yes?

I would expect to code something like

Code: Select all

startPoints []
endPoints[]
selObjs = Gui.Selection.getSelection
for obj in selObjs:
	startPoints.append(obj.Geometry[0].StartPoint)
	endPoints.append(obj.Geometry[-1].EndPoint

toSketch workbench uses the python library geomdl
For curve fit toSketch has a function

Code: Select all

def fitCurve(self, npPointBuff, numControlPoints):
        from geomdl import fitting
        print(f"evaluate Curve number of control points {numControlPoints}")
        degree = 3
        #curve = fitting.approximate_curve(pointBuff, degree, \
        curve = fitting.approximate_curve(npPointBuff, degree, \
                centripetal=True, ctrlpts_size = numControlPoints)
        return curve

So I would create a PointBuff from the startPoints and EndPoints and adapt the function accordingly.
You probably want to add code to check that you are dealing with a Sketch and the start and endpoints
are Part.LineSegment (s)

Once you have the fitted curve use something like

Code: Select all

	fcCp = []
		for cp in curve._control_points :
		print(f'cp {cp}')
		fcCp.append(FreeCAD.Vector(cp[0],cp[1],0))
	print(curve.degree)
	print(curve._geometry_type)
	print(f"Number of Control points : {len(curve._control_points)}")
	print(f"Knot Vector : {curve.knotvector}")
	print(f"Weights : {curve.weights}")
	self.sketch.addGeometry(Part.BSplineCurve(fcCp,None,None,False,\
                    curve.degree,None,False))
edwilliams16
Veteran
Posts: 3108
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Collecting vertexes/points to pass to a bspline function

Post by edwilliams16 »

Maybe this will be useful

Code: Select all

import Draft
doc = App.ActiveDocument
obj = doc.getObject("cs_plane_sketch")
shp = obj.Shape
vpointsplus = [v.Point for v in shp.Vertexes if v.Point.x > 0]
vpointsminus = [v.Point for v in shp.Vertexes if v.Point.x < 0]
Draft.makeBSpline(vpointsplus)
Draft.makeBSpline(vpointsminus)
doc.recompute()
Screenshot 2023-01-29 at 1.47.18 PM.png
Screenshot 2023-01-29 at 1.47.18 PM.png (21.49 KiB) Viewed 658 times
mconsidine
Posts: 125
Joined: Wed Jan 18, 2023 10:41 pm
Location: Randolph, VT USA

Re: Collecting vertexes/points to pass to a bspline function

Post by mconsidine »

@edwilliams16 Yes, I'd say that would be pretty darn useful. :)

Thank you very much! I'll code it up tomorrow and see what happens.

Fwiw, I believe a posting you made that was similar (but dealt with Points), was noted as an inspiration. I obviously couldn't transfer that into my context, so thank you for chiming in and for sett6 me straight

Regards,
mconsidine
mconsidine
Posts: 125
Joined: Wed Jan 18, 2023 10:41 pm
Location: Randolph, VT USA

Re: Collecting vertexes/points to pass to a bspline function

Post by mconsidine »

@keithsloan52 Thank you as well. I'll take a look at that solution as well. In the real working example (ie a maximally nonworking example, "MNWE") I've got to try to get the curve through a half dozen points, and the hopefully add some thickness *inwards*, as the constraints are essentially outer ones.

Your example may help there.

Thanks again.

mconsidine
edwilliams16
Veteran
Posts: 3108
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Collecting vertexes/points to pass to a bspline function

Post by edwilliams16 »

@mconsidine
BTW

Code: Select all

offset = selobj[0].Shape.Placement.Base * FreeCAD.Vector(0,1,0) #find any offset to XZ plane at origin
is an obscure way to get the y-component of the vector

Code: Select all

offset = selobj[0].Shape.Placement.Base.y #find any offset to XZ plane at origin
is more straightforward. I had to look up that between vectors, * overloads to their dot product. (It also overloads to scalar and matrix products!)

Code: Select all

dir = FreeCAD.Vector(1, 1, 1).normalize()
offsetcomponent = selobj[0].Shape.Placement.Base.dot(dir) #component in direction dir 
would be more readable, to me at least, were the offset not in a principal axis direction.
mconsidine
Posts: 125
Joined: Wed Jan 18, 2023 10:41 pm
Location: Randolph, VT USA

Re: Collecting vertexes/points to pass to a bspline function

Post by mconsidine »

@edwilliams16 Thanks for the clarification and pointer. Where I was going with that was trying to figure out how to get values in the event that the cutting plane was not just XZ but ultimately arbitrarily oriented.

But that's way down the road (if at all) and I shouldn't have confused things by including some thought-in-progress.

Thanks again,
mconsidine
mconsidine
Posts: 125
Joined: Wed Jan 18, 2023 10:41 pm
Location: Randolph, VT USA

Re: Collecting vertexes/points to pass to a bspline function

Post by mconsidine »

Thanks again for everyone's help. I've made a bit more progress and have another question on this.

I've attached an example of the sketchs I'm working with, along with a new macro file.
Screenshot from 2023-01-30 18-38-05.png
Screenshot from 2023-01-30 18-38-05.png (8.58 KiB) Viewed 405 times
The short question is: is there some logic that can be applied to get rid of the "fins" of the 4 walls. Ie, I'm trying to figure out how the surfaces "inside" the intersecting corners can be kept, while the surface "outside" of the corners can be discarded, with the result being combined into a single shape whose edges I can round? I've been playing all day with the union, intersection, cut, etc functions and nothing is getting me there.

Does anyone know a trick they can point me to?

TIA,
mconsidine
Attachments
test2.FCMacro
(4.82 KiB) Downloaded 7 times
a_test.FCStd
(22.65 KiB) Downloaded 6 times
Post Reply