Tangentiale Übergänge

Wie können Übergänge zwischen zwei Freiformflächen aussehen? Neben der harten Kante sind auch weiche Übergänge möglich.

*Skript (3.88 KiB, 3M ago, 34 downloads) *

2017/05/19 22:55

Farbige Darstellung von Werten

Für einen objektabhängigen Wert soll seine Abweichung von einem Wunschwert angezeigt werden. Im konkreten Beispiel geht es um die Länge einer Kurve (BSpline). Wird die Kurve bei der Bearbeitung zu lang, soll sie sich rot färben, wird sie zu kurz, soll sie blau werden.

Die einfachste Lösung ist ein Part::FeaturePython Objekt, welches die Kurve als Parameter verwendet und bei jeder Veränderung der Kurve deren Länge berechnet und mit den Vorgaben vergleicht.

spline = Draft.makeBSpline(points,closed=False,face=True,support=None)

a=FreeCAD.activeDocument().addObject("Part::FeaturePython","MyMonitor")
m=Monitor(a)

a.source=spline
a.minVal= spline.Shape.Length*0.95
a.maxVal= spline.Shape.Length*1.05

Die Monitor-Klasse erledigt die Überwachungs- und Färbearbeit. Sie ist im Skript enthalten.

Bei Abweichungen über die Genzen hinaus wird die Kurve neu gefärbt. Das erledigt die execute-Methode.

def execute(proxy,obj):
	mm=20
	if obj.source <> None:
			print ("Value and interval:", round(obj.source.Shape.Edge1.Length,1),obj.minVal,obj.maxVal)
			obj.source.ViewObject.LineColor=(1.0,1.0,1.0)
			if obj.source.Shape.Edge1.Length<obj.minVal:
				obj.source.ViewObject.LineColor=(0.0,.0,1.0)
			elif obj.source.Shape.Edge1.Length>obj.minVal and obj.source.Shape.Edge1.Length<obj.minVal+mm:
				j=1-(obj.minVal+mm-obj.source.Shape.Edge1.Length)/mm
				j=j*0.5
				obj.source.ViewObject.LineColor=(j,j,1.0)
			elif obj.source.Shape.Edge1.Length<obj.maxVal and obj.source.Shape.Edge1.Length>obj.maxVal-mm:
				j=(obj.maxVal-obj.source.Shape.Edge1.Length)/mm
				j=j*0.5
				obj.source.ViewObject.LineColor=(1.0,j,j)
			elif obj.source.Shape.Edge1.Length>obj.maxVal:
				obj.source.ViewObject.LineColor=(1.0,0.0,.0)

  • Skript (3.56 KiB, 3M ago, 43 downloads)
2017/04/24 23:50

How to create a Driver Sketch

Using Expressions it is possible to create and use a simplified sketch to drive a more complex sketch The idea is to map the blue constraints of the driver to some red constraints in the driven sketch.

The driver is created as a hexagon (red)

The driven sketch is a shoe rib sketch from the Nurbs Workbench project (yellow).

import nurbswb
import nurbswb.createshoerib
nurbswb.createshoerib.run()

The mapping between the constraints is donme by related name lists

inputs=[ 
		'x0','y0',
		'x1','y1',
		'x2','y2',
		'x3','y3',
		'x4','y4',
		'x5','y5'
	]

outputs=[ 
		'p0X', 'p0Y',  
		'p2X', 'p2Y',
		'p4X', 'p4Y',
		'p8X', 'p8Y',
		'p12X', 'p12Y',
		'p14X', 'p14Y',
	]

The expression can be done by script this way

rc=target.setExpression('Constraints.'+outputs[i], source.Name+".Constraints."+inputs[i])

2017/04/18 20:04

Paralleles Editieren von Daten

Möchte man mehrere Kurven gleichzeitig bearbeiten, kann man für jedes Objekt einen eigenen Bearbeitsdialog erstellen. Diese Dialoge können dann auf der arbeitsfläche verteilt werden.

Im Beispiel werden Beschränkungen in Skizzen für die Gewichte der Pole von Splines durch Schieberegler verändert.

Das Verfahren lässt sich auch auf andere skalare Größen wie etwa die Lage der Knoten anwenden. Auf diesem Weg bekommt man schnell den Zugriff auf die volle Formen-Vielfalt der NURBS und die Datenmenge lässt sich noch überschaubar anordnen.

Der Vorteil gegenüber eines Ansatzes mit einem Spreadsheet: Es werden nur die Datenreihen angezeigt, die aktuell wirklich gebraucht werden. Und die Daten stehen in der Nähe ihres Wirkungskreises.

Skript (1.54 KiB, 5M ago, 53 downloads)

2017/03/15 14:06

From a Pointcloud slice to a sketcher spline

Point cloud slices are planar point clouds which can be used to create 2D curves.

These slices can be generated simply from images with edge detection algorithms. An other way is to slice 3D Point clouds.

A point cloud holds typically thousends of points. And the points are not located on exact positions. Scanner and Cameras generate some rounding errors and noise.

It's interesting to have a way from such a point cloud back to an near exact CAD model.

This is an introduction how to achieve this with FreeCAD.

It's for the special case where the curve is closed and has it's center of mass inside on a position where for any point its connecting line to the center is completly inside the „figure“.

These are the steps to proceed.

  1. Generate some randomized test data or get a point cloud from a use case
  2. Create a first set of approximations as Polygons
  3. Create Draft Bsplines for this first approximations
  4. Convert the Draft Bsplines to Sketcher Bsplines

All methods are stored in the nurbs workbench but can be used standalone.

Random Data Set

The dataset of 1000 points are points around the origin with mean distance rm and To have more irregularitiy we overlay all with two sine waves.

count=1000
ri=100
rm=400

# random ankle
kaps=np.random.random(count)*2*np.pi

#random radius
rads=np.random.random(count)*ri*np.cos(kaps*5)*np.cos(kaps*1.3) + rm

y= np.cos(kaps) * rads
x=np.sin(kaps) * rads
z=np.zeros(count)

pps=np.array([x,y,z]).swapaxes(0,1)
goods=[FreeCAD.Vector(tuple(p)) for p in pps]

Points.show(Points.Points(goods))

To run the script we import the nurbswb and the script and call its run function.

import nurbswb;
import nurbswb.gen_random_dat;
nurbswb.gen_random_dat.run()

First Approximation

There are different ways to get an approximation of a curve. The simplest is to create a circle. The center is the center of mass of the point cloud.

Then there are at least 3 main approches:

  • The outer circle is the „round version“ of the BoundBox. All but the noise points should lie inside.
  • The inner circle is the maximum circle around the center without any point in it.

If we have the point cloid as a volume inner and outer circle can be used to make something like a tube or a worm.

  • A 3rd simple way to get a circle is the medium circle with the mean radius of the cloud.

More complex is to order the points in a useful way and to connect them to a polygon. Because there can be a local noise of points some local average processing is needed.

For a outer and inner polygon the extrema of the distances to the center can be used. The strategy is: Jump from one top to the next.

First the center of the cloud and the distances of all points from this center is calculated.

npts=np.array(pts).swapaxes(0,1)
mp=(npts[0].mean(),npts[1].mean(),npts[2].mean())

# center
vm=FreeCAD.Vector(mp)
# distances of all points
lengths=np.array([(FreeCAD.Vector(p)-vm).Length for p in pts])

Later the directions of each point viewd from center is used to order the points.Note that this is essential. The calcualted curve cannot change its direction forward and backward as when writing a S-curve. For such cases an other method is required.

for v in pts:
	vn=v-vm
	aps[np.arctan2(vn.x,vn.y)]=vn
	rads[np.arctan2(vn.x,vn.y)]=vn.Length

kaps=aps.keys()
kaps.sort()

#the poits ordered and its distances
ptss=[aps[k] for k in kaps]
radss=[rads[k] for k in kaps]

kaps is a list of all directions. If there are gaps in this list an extra interpolation step which fills these gaps makes sence.

If the median approximation is calculated the radia have to be smoothed. This is done with the scipy.signal.medfilt method. The size of the window is configurable.

l=np.array(radss)
f=medianfilterwindow
path=np.concatenate([[l[0]] * f,l,[l[-1]]*f])
l2 = sp.signal.medfilt(path,f)
mmaa=l2[f:-f]

For the outer curves a jumping sequence form one top to the next is needed. This is done with the scipy.signal.argrelextrema method.

if inner:
   z1=argrelextrema(radss, np.less)
else:
   z1=argrelextrema(radss, np.greater)

And at last the gaps are filled with numpy.interp.

So the method generates 3 circles and 3 wires: inner green, outer red and intermediate blue.

How to use:

import nurbswb;
import nurbswb.orderpoints;
nurbswb.orderpoints.run()

From Wire to Bspline

In the next step a Bspline is approximated. The Part.BSpline approximate method is the first step. But its result has too many poles for later editing by hand.

There is an extra reduce process: The curvature of the first approximated curve is computed and then only points where the curvature has extrem values are used as places for poles

bc=Part.BSplineCurve()
bc.approximate(pts,DegMax=3,Tolerance=1)
bc.setPeriodic()

Once again the scipy.signal.argrelextrema method is a good friend.

vps=np.array([bc.value(1.0/ct*i)+off for i in x])
y=np.array([sc.curvatureAt(1.0/ct*i) for i in x])

z=argrelextrema(y, np.greater)
z2=argrelextrema(y, np.less)

zc=np.concatenate([z,z2,[0,ct]])
zc.sort()
exps=vps[zc]

ps=[tuple(p) for p in exps]
Draft.makeBSpline(ps,closed=True,face=False)

There is a parameter how fine the starting curve is inspected.

How to use:

import nurbswb;
import nurbswb.simplecurve;
nurbswb.simplecurve.run()

Draft BSpline to Sketcher BSpline

From the Draft BSpline to the Sketcher BSpline its not a big step. Take the poles over and create the helper stuff.

sk.addGeometry(Part.BSplineCurve(l,True),False)

conList = []

for i,p in enumerate(pts):
   conList.append(Sketcher.Constraint('InternalAlignment:Sketcher::BSplineControlPoint',i,3,k,i))

sk.addConstraint(conList)

How to use:

import nurbswb;
import nurbswb.createsketchspline;
nurbswb.createsketchspline.run()

Configruation of the methods

2017/03/12 11:54

Ältere Einträge >>

Archiv

Blog-Archiv

2016-01: 3 Einträge 2016-02: 4 Einträge 2016-03: 2 Einträge 2016-05: 2 Einträge 2016-08: 3 Einträge 2016-09: 9 Einträge 2016-10: 7 Einträge 2016-11: 11 Einträge 2016-12: 3 Einträge

2016

Dezember

November

Oktober

September

August

Mai

März

Februar

Januar

Blog-Archiv

2015-01: 13 Einträge 2015-02: 9 Einträge 2015-03: 5 Einträge 2015-04: 7 Einträge 2015-05: 1 Eintrag 2015-07: 6 Einträge 2015-08: 1 Eintrag 2015-09: 2 Einträge 2015-10: 5 Einträge 2015-11: 7 Einträge 2015-12: 7 Einträge

2015

Dezember

November

Oktober

September

August

Juli

Mai

April

März

Februar

Januar

Blog-Archiv

2014-02: 1 Eintrag 2014-03: 3 Einträge 2014-04: 6 Einträge 2014-05: 2 Einträge 2014-07: 1 Eintrag 2014-09: 14 Einträge 2014-10: 23 Einträge 2014-11: 13 Einträge 2014-12: 9 Einträge

2014

Dezember

November

Oktober

September

Juli

Mai

April

März

Februar

blog.txt · Zuletzt geändert: 2017/03/12 13:12 von freek