-
Notifications
You must be signed in to change notification settings - Fork 1
/
comp_optic.py
2464 lines (2072 loc) · 97.6 KB
/
comp_optic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# ----------------------------------------------------------------------------
# -- Components
# -- comps library
# -- Python classes that creates optical components
# ----------------------------------------------------------------------------
# -- (c) Felipe Machado
# -- Area of Electronic Techonology. Rey Juan Carlos University (urjc.es)
# -- July-2017
# ----------------------------------------------------------------------------
# --- LGPL Licence
# ----------------------------------------------------------------------------
import FreeCAD
import Part
import logging
import os
import Draft
import DraftGeomUtils
import DraftVecUtils
import math
#import copy
import Mesh
import MeshPart
# ---------------------- can be taken away after debugging
# directory this file is
filepath = os.getcwd()
import sys
# to get the components
# In FreeCAD can be added: Preferences->General->Macro->Macro path
sys.path.append(filepath)
# ---------------------- can be taken away after debugging
import kcomp
import kcomp_optic
import fcfun
import kparts
from fcfun import V0, VX, VY, VZ, V0ROT, addBox, addCyl, addCyl_pos, fillet_len
from fcfun import VXN, VYN, VZN
from fcfun import addBolt, addBoltNut_hole, NutHole
logging.basicConfig(level=logging.DEBUG,
format='%(%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# ---------------------- CageCube -------------------------------
class CageCube (object):
""" Creates Cage Cube for optics
taps are only drawn with their max diameter,
setscrews and taps to secure the rods are not drawn
Args
side_l: length of the side of the cube
thru_hole_d: big thru-hole on 2 sides, not threaded, centered
thru_thread_d: 2 big thru-hole threaded, on 4 sides, centered
thru_rod_d: 4 thru holes, on 2 sides
thru_rod_sep: separation of the rods
rod_thread_d: on the sides other than the thru_rods, there are threads
to insert a rod
rod_thread_l: depth of the thread for the rods
tap_d: diameter of the tap to connect accesories
tap_l: depth of the taps to connect accesories
tap_sep_l: separation of the tap to connect, large
tap_sep_s: separation of the tap to connect, sort
axis_thru_rods: direction of rods: 'x', 'y', 'z'
axis_thru_hole: direction big thru_hole: 'x', 'y', 'z'.
Cannot be the same as axis_thru_rods
There are 6 posible orientations:
Thru-rods can be on X, Y or Z axis
thru-hole can be on X, Y, or Z axis, but not in the same as thru-rods
"""
ROD_SCREWS = kcomp_optic.ROD_SCREWS
THRU_RODS = kcomp_optic.THRU_RODS
THRU_HOLE = kcomp_optic.THRU_HOLE
def __init__ (self, side_l,
thru_hole_d,
thru_thread_d,
thru_rod_d,
thru_rod_sep,
rod_thread_d,
rod_thread_l,
tap_d,
tap_l,
tap_sep_l,
tap_sep_s,
axis_thru_rods = 'x',
axis_thru_hole = 'y',
name = 'cagecube'):
doc = FreeCAD.ActiveDocument
self.base_place = (0,0,0)
self.side_l = side_l
self.thru_hole_d = thru_hole_d
self.thru_thread_d = thru_thread_d
self.thru_rod_d = thru_rod_d
self.axis_thru_rods = axis_thru_rods
self.axis_thru_hole = axis_thru_hole
# getting the freecad vector of the axis
self.v_thru_rods = fcfun.getfcvecofname(axis_thru_rods)
self.v_thru_hole = fcfun.getfcvecofname(axis_thru_hole)
# get the 3rd perpendicular vector
self.v_rod_screws = self.v_thru_rods.cross (self.v_thru_hole)
# cage
shp_cage_box = fcfun.shp_boxcen(x=side_l,
y=side_l,
z=side_l,
cx=1, cy=1, cz=1,
pos=V0)
# centered Thru hole: 1
shp_thru_hole_cen0 = fcfun.shp_cylcenxtr (r= thru_hole_d/2.,
h = side_l,
normal = self.v_thru_hole,
ch=1, xtr_top=1., xtr_bot=1.,
pos = V0)
holes = []
#holes.append(shp_thru_hole_cen0)
# threaded thru-holes, centered:2
# getting the perpendicular directions of v_thru_hole
# if (1,0,0) -> (0,1,0)
v_thru_hole_perp1 = FreeCAD.Vector(self.v_thru_hole.y,
self.v_thru_hole.z,
self.v_thru_hole.x);
shp_thru_hole_cen1 = fcfun.shp_cylcenxtr (r= thru_thread_d/2.,
h = side_l,
normal = v_thru_hole_perp1,
ch=1, xtr_top=1., xtr_bot=1.,
pos = V0)
holes.append(shp_thru_hole_cen1)
v_thru_hole_perp2 = FreeCAD.Vector(self.v_thru_hole.z,
self.v_thru_hole.x,
self.v_thru_hole.y);
shp_thru_hole_cen2 = fcfun.shp_cylcenxtr (r= thru_thread_d/2.,
h = side_l,
normal = v_thru_hole_perp2,
ch=1, xtr_top=1., xtr_bot=1.,
pos = V0)
holes.append(shp_thru_hole_cen2)
# thru-holes for the rods:
# dimensions are added to the axis other than the normal
fc_list = fcfun.get_fclist_4perp2_vecname(axis_thru_rods)
for fcvec in fc_list:
fc_dist = DraftVecUtils.scale(fcvec, thru_rod_sep/2.)
shp_thru_hole_rod = fcfun.shp_cylcenxtr (r= thru_rod_d/2.,
h = side_l,
normal = self.v_thru_rods,
ch=1, xtr_top=1., xtr_bot=1.,
pos = fc_dist)
holes.append(shp_thru_hole_rod)
# taps to connect rods. 4 in 4 sides (not on the side of the thru-holes
# for the rods
# get the four directions, of the normals
fc_rodtap_list = fcfun.get_fclist_4perp_vecname(axis_thru_rods)
for vnormal in fc_rodtap_list:
# for each normal, we take the other 4 perpendicular axis
# for example, is vnormal is (1,0,0), the 4 perpendicular axis
# will be (0,1,1), (0,-1,1), (0,-1,-1), (0,1,-1)
fc_perp_coord_list = fcfun.get_fclist_4perp2_fcvec(vnormal)
vnormal_coord = DraftVecUtils.scale(vnormal,
(side_l/2. -rod_thread_l))
for fc_perp_coord in fc_perp_coord_list:
fc_perp_coord_scale = DraftVecUtils.scale(fc_perp_coord,
thru_rod_sep/2.)
fc_coord = fc_perp_coord_scale + vnormal_coord
shp_rodtap = fcfun.shp_cylcenxtr (r= rod_thread_d/2,
h = rod_thread_l,
normal = vnormal,
ch=0, xtr_top =1.,
xtr_bot=0,
pos = fc_coord)
holes.append (shp_rodtap)
# taps for mounting a cover, on the 2 sides of the centered thru-hole
# direction: self.v_thru_hole and negated
for vnormal in [self.v_thru_hole, DraftVecUtils.neg(self.v_thru_hole)]:
vnormal_coord = DraftVecUtils.scale(vnormal,
(side_l/2. -tap_l))
# the large separation is the same as the thru rods
for vdir_large in [self.v_thru_rods,
DraftVecUtils.neg(self.v_thru_rods)]:
#scale this direction to the length of the separation (half)
fc_coord_large = DraftVecUtils.scale(vdir_large, tap_sep_l/2.)
# the sort separation: cross product
vdir_short = vnormal.cross (vdir_large)
vdir_short.normalize()
for vdir_short_i in [vdir_short, DraftVecUtils.neg(vdir_short)]:
fc_coord_short = DraftVecUtils.scale(vdir_short_i,
tap_sep_s/2.)
fc_coord = vnormal_coord + fc_coord_large + fc_coord_short
shp_tap = fcfun.shp_cylcenxtr (r= tap_d/2,
h = tap_l,
normal = vnormal,
ch=0, xtr_top =1.,
xtr_bot=0,
pos = fc_coord)
holes.append (shp_tap)
shp_holes = shp_thru_hole_cen0.multiFuse(holes)
shp_holes = shp_holes.removeSplitter()
shp_cage = shp_cage_box.cut(shp_holes)
doc.recompute()
fco_cage = doc.addObject("Part::Feature", name )
fco_cage.Shape = shp_cage
self.fco = fco_cage
def BasePlace (self, position = (0,0,0)):
self.base_place = position
self.fco.Placement.Base = FreeCAD.Vector(position)
def color (self, color = (1,1,1)):
self.fco.ViewObject.ShapeColor = color
def vec_face (self, fcv):
"""Return which face of the cube corresponds to the direction fcv
Arguments:
fcf -- FreeCAD.Vector pointing to the normal of the cube face
we want to check
returns: a string indicating the face. There are 3 different cube
faces:
'thruhole' : the face with the big central hole is a thruhole
without threads
'thrurods' : the face that has 4 thruholes for the rods and a
threaded big central hole
'rodscrews': the face has 4 tapped holes for screwing the
end of the rods and a threaded big central hole
'none': the vector isn't parallel to any of the faces of the cube
"""
#normalize the vector:
nv = DraftVecUtils.scaleTo(fcv,1)
if fcfun.fc_isparal(self.v_thru_hole, nv):
return self.THRU_HOLE
elif fcfun.fc_isparal(self.v_thru_rods, nv):
return self.THRU_RODS
elif fcfun.fc_isparal(self.v_rod_screws, nv):
return self.ROD_SCREWS
else:
return 0
def get_cenhole_d (self, face):
""" Given a face defined in kcomp_optic.py, returns the size of the
central hole
Arguments:
face: THRU_HOLE (3), THRU_RODS (2), ROD_SCREWS (1)
"""
if face == self.THRU_HOLE:
return self.thru_hole_d
elif face == self.THRU_RODS or face == self.ROD_SCREWS:
return self.thru_thread_d
else:
logger.debug('wrong value of face of cage cube')
return 0
# ------------------ END CageCube ------------------------------
# ------------------ f_cagecube ------------------------------
def f_cagecube (d_cagecube,
axis_thru_rods = 'x',
axis_thru_hole = 'y',
name = 'cagecube',
toprint_tol = 0,
):
""" creates a cage cube, it creates from a dictionary
Args
d_cagecube: dictionary with the dimensions of the cage cube,
defined in kcomp_optic.py
axis_thru_rods: direction of rods: 'x', 'y', 'z'
axis_thru_hole: direction big thru_hole: 'x', 'y', 'z'.
Cannot be the same as axis_thru_rods
There are 6 posible orientations:
Thru-rods can be on X, Y or Z axis
thru-hole can be on X, Y, or Z axis, but not in the same as thru-rods
toprint_tol: 0, dimensions as they are.
>0 value of tolerances of the holes.
multiplies the normal tolerance in kcomp.TOL
Returns a class of a CageCube. The freeCAD object can be accessed by the
attribute .fco
"""
if toprint_tol > 0:
tol = toprint_tol * kcomp.TOL
tol_plus = 1.5 * toprint_tol * kcomp.TOL
else:
tol = 0
tol_plus = 0
print ('tol: ' + str(tol))
print ('tol_plus: ' + str(tol_plus))
cage = CageCube(side_l = d_cagecube['L'],
thru_hole_d = d_cagecube['thru_hole_d'] + tol,
thru_thread_d = d_cagecube['thru_thread_d'] + tol,
thru_rod_d = d_cagecube['thru_rod_d'] + tol_plus,
thru_rod_sep = d_cagecube['thru_rod_sep'],
rod_thread_d = d_cagecube['rod_thread_d'] + tol,
rod_thread_l = d_cagecube['rod_thread_l'] + tol,
tap_d = d_cagecube['tap_d'] + tol,
tap_l = d_cagecube['tap_l'] + tol,
tap_sep_l = d_cagecube['tap_sep_l'],
tap_sep_s = d_cagecube['tap_sep_s'],
axis_thru_rods = axis_thru_rods,
axis_thru_hole = axis_thru_hole,
name = name)
return cage
#doc = FreeCAD.newDocument()
#doc = FreeCAD.ActiveDocument
# Cage cube to print, with tolerances
#dcube = kcomp_optic.CAGE_CUBE_60
#h_cage_c = f_cagecube(dcube,
# axis_thru_rods= 'z', axis_thru_hole='x',
# name = "cube60_tol",
# toprint_tol = 1)
# ---------------------- CageCubeHalf -------------------------------
class CageCubeHalf (object):
""" Creates a Half Cage Cube for optics, so you can put the lense
at 45
taps are only drawn with their max diameter,
setscrews and taps to secure the rods are not drawn
Many other details are not drawn, neither the cover for the lense
The right angle sides are identical, but there is a difference
regarding to the tapped holes on the sides, the can have different
sizes
Args
side_l: length of the side of the cube (then it will be halved)
thread_d: 2 big threads, on the 2 perpendicular sides, centered
thru_hole_d: internal hole after the thread
thru_hole_depth: depth from which the thru hole starts
lenshole_45_d: hole from the 45 angle side that will go to the center
rod_d: 4 holes, on 2 sides, perpendicular sides. The rods will be
secured with screws, but those screws are not drawn
rod_sep: separation of the rods
rod_depth: how deep are the holes
rod_thread_l: depth of the thread for the rods
tap_d: diameter of the tap to connect accesories
tap_l: depth of the taps to connect accesories
tap_sep_l: separation of the tap to connect, large
tap_sep_s: separation of the tap to connect, sort
axis_1: direction of the first right side:
'x', 'y', 'z', '-x', '-y', '-z'
axis_2: direction big the other right side:
'x', 'y', 'z', '-x', '-y', '-z'
Cannot be the same as axis_1, or its negated. Has to be perpendicular
There are 24 posible orientations:
6 posible axis_1 and 4 axis_2 for each axis_1
name: name of the freecad object
"""
def __init__ (self, side_l,
thread_d,
thru_hole_d,
thru_hole_depth,
lenshole_45_d,
rod_d,
rod_sep,
rod_depth,
tap12_d,
tap12_l,
tap21_d,
tap21_l,
tap_dist,
axis_1 = 'x',
axis_2 = 'y',
name = 'cagecube'):
doc = FreeCAD.ActiveDocument
self.base_place = (0,0,0)
self.side_l = side_l
self.thread_d = thread_d
self.thru_hole_d = thru_hole_d
self.thru_hole_depth = thru_hole_depth
self.lenshole_45_d = lenshole_45_d
self.rod_d = rod_d
self.rod_sep = rod_sep
self.rod_depth = rod_depth
self.axis_1 = axis_1
self.axis_2 = axis_2
# getting the freecad vector of the axis
self.v_1 = fcfun.getfcvecofname(axis_1)
self.v_2 = fcfun.getfcvecofname(axis_2)
# cage
shp_cage_box = fcfun.shp_boxcen(x=side_l,
y=side_l,
z=side_l,
cx=1, cy=1, cz=1,
pos=V0)
# taking the half away (it is less than the half)
# the normal is on the opposite direction of the sum of axis_1 and
# axis_2
v_halfout = DraftVecUtils.neg(self.v_1 + self.v_2)
v_halfout.normalize()
# Making the cut with a cilinder, because it is easier, since the
# function is already availabe
# radius is smaller: pythagoras, but to make it simpler
# the position is not just the half, about a centimeter less, but
# just thake the thru_hole_depth
pos_halfout = DraftVecUtils.scaleTo(v_halfout, thru_hole_depth)
shp_halfout = fcfun.shp_cyl(r= side_l, h=side_l,
normal = v_halfout,
pos = pos_halfout)
doc.recompute()
#Part.show(shp_halfout)
# hole on the 45 face, for the lense
# on position (0,0,0) but the same direction as the previous
# the heigth is hypotenuse, but to symplify and to cut over the total
# length, we make it twice the cathetus
shp_lensehole = fcfun.shp_cyl(r= lenshole_45_d/2.,
h=2*thru_hole_depth,
normal = v_halfout,
pos = V0)
# make the cut know because freecad was having problems making the cut
# all together, maybe because there 45 degrees cuts that
shp_45cut = shp_halfout.fuse(shp_lensehole)
shp_cage_half = shp_cage_box.cut(shp_45cut)
shp_cage_half = shp_cage_half.removeSplitter()
doc.recompute()
#Part.show(shp_cage_half)
holes = []
# threaded holes, centered:2
pos_thread_1 = DraftVecUtils.scale(self.v_1, side_l/2.-thru_hole_depth)
shp_thread_1 = fcfun.shp_cylcenxtr (r= thread_d/2.,
h = thru_hole_depth,
normal = self.v_1,
ch=0, xtr_top=1., xtr_bot=0.,
pos = pos_thread_1)
# Not included in the list, because one element has to be out
#holes.append(shp_thread_1)
pos_thread_2 = DraftVecUtils.scale(self.v_2, side_l/2.-thru_hole_depth)
shp_thread_2 = fcfun.shp_cylcenxtr (r= thread_d/2.,
h = thru_hole_depth,
normal = self.v_2,
ch=0, xtr_top=1., xtr_bot=0.,
pos = pos_thread_2)
holes.append(shp_thread_2)
# thru holes, centered:2, on the direction of right angles
shp_thru_1 = fcfun.shp_cylcenxtr (r= thru_hole_d/2.,
h = side_l,
normal = self.v_1,
ch=1, xtr_top=1., xtr_bot=1.,
pos = V0)
holes.append(shp_thru_1)
shp_thru_2 = fcfun.shp_cylcenxtr (r= thru_hole_d/2.,
h = side_l,
normal = self.v_2,
ch=1, xtr_top=1., xtr_bot=1.,
pos = V0)
holes.append(shp_thru_2)
# holes to connect rods. 4 in 2 sides (perpendicular sides)
# get the four directions, of the normals
for vnormal in [self.v_1, self.v_2]:
# for each normal, we take the other 4 perpendicular axis
# for example, is vnormal is (1,0,0), the 4 perpendicular axis
# will be (0,1,1), (0,-1,1), (0,-1,-1), (0,1,-1)
fc_perp_coord_list = fcfun.get_fclist_4perp2_fcvec(vnormal)
# position on the normal dimension (where the rod hole starts)
vnormal_coord = DraftVecUtils.scale(vnormal,
(side_l/2. -rod_depth))
for fc_perp_coord in fc_perp_coord_list:
fc_perp_coord_scale = DraftVecUtils.scale(fc_perp_coord,
rod_sep/2.)
fc_coord = fc_perp_coord_scale + vnormal_coord
shp_rodhole = fcfun.shp_cylcenxtr (r= rod_d/2,
h = rod_depth,
normal = vnormal,
ch=0, xtr_top =1.,
xtr_bot=0,
pos = fc_coord)
holes.append (shp_rodhole)
# taps to mount to posts
# get the direction axis_1 x axis_2
vdir_12 = self.v_1.cross (self.v_2)
vdir_21 = self.v_2.cross (self.v_1)
axis1_coord = DraftVecUtils.scale(self.v_1, tap_dist)
axis2_coord = DraftVecUtils.scale(self.v_2, tap_dist)
axis12_coord = DraftVecUtils.scale(vdir_12, side_l/2. - tap12_l)
axis21_coord = DraftVecUtils.scale(vdir_21, side_l/2. - tap21_l)
fc_pos12 = axis1_coord + axis2_coord + axis12_coord
fc_pos21 = axis1_coord + axis2_coord + axis21_coord
shp_tap12 = fcfun.shp_cylcenxtr (r = tap12_d/2,
h = tap12_l,
normal = vdir_12,
ch=0, xtr_top =1.,
xtr_bot=0,
pos = fc_pos12)
shp_tap21 = fcfun.shp_cylcenxtr (r = tap21_d/2,
h = tap21_l,
normal = vdir_21,
ch=0, xtr_top =1.,
xtr_bot=0,
pos = fc_pos21)
holes.append (shp_tap12)
holes.append (shp_tap21)
shp_holes = shp_thread_1.multiFuse(holes)
shp_holes = shp_holes.removeSplitter()
doc.recompute()
#Part.show(shp_holes)
shp_cage_holes = shp_cage_half.cut(shp_holes)
doc.recompute()
fco_cage = doc.addObject("Part::Feature", name )
fco_cage.Shape = shp_cage_holes
self.fco = fco_cage
def BasePlace (self, position = (0,0,0)):
self.base_place = position
self.fco.Placement.Base = FreeCAD.Vector(position)
def color (self, color = (1,1,1)):
self.fco.ViewObject.ShapeColor = color
def f_cagecubehalf (d_cagecubehalf,
axis_1 = 'x',
axis_2 = 'y',
name = 'cagecubehalf'
):
""" creates a half cage cube: 2 perpendicular sides, and a 45 degree angle
side,
it creates from a dictionary
Args
d_cagecubehalf: dictionary with the dimensions of the cage cube,
defined in kcomp_optic.py
axis_1: direction of the first right side:
'x', 'y', 'z', '-x', '-y', '-z'
axis_2: direction big the other right side:
'x', 'y', 'z', '-x', '-y', '-z'
Cannot be the same as axis_1, or its negated. Has to be perpendicular
There are 24 posible orientations:
6 posible axis_1 and 4 axis_2 for each axis_1
name: name of the freecad object
"""
cage = CageCubeHalf(
side_l = d_cagecubehalf['L'],
thread_d = d_cagecubehalf['thread_d'],
thru_hole_d = d_cagecubehalf['thru_hole_d'],
thru_hole_depth = d_cagecubehalf['thru_hole_depth'],
lenshole_45_d = d_cagecubehalf['lenshole_45_d'],
rod_d = d_cagecubehalf['rod_d'],
rod_sep = d_cagecubehalf['rod_sep'],
rod_depth = d_cagecubehalf['rod_depth'],
tap12_d = d_cagecubehalf['tap12_d'],
tap12_l = d_cagecubehalf['tap12_l'],
tap21_d = d_cagecubehalf['tap21_d'],
tap21_l = d_cagecubehalf['tap21_l'],
tap_dist = d_cagecubehalf['tap_dist'],
axis_1 = axis_1,
axis_2 = axis_2,
name = name)
return cage
#cage = f_cagecubehalf(kcomp_optic.CAGE_CUBE_HALF_60)
#cage = CageCube(side_l = kcomp_optic.CAGE_CUBE_60['L'],
# thru_hole_d = kcomp_optic.CAGE_CUBE_60['thru_hole_d'],
# thru_thread_d = kcomp_optic.CAGE_CUBE_60['thru_thread_d'],
# thru_rod_d = kcomp_optic.CAGE_CUBE_60['thru_rod_d'],
# thru_rod_sep = kcomp_optic.CAGE_CUBE_60['thru_rod_sep'],
# rod_thread_d,
# rod_thread_l,
# tap_d,
# tap_l,
# tap_sep_l,
# tap_sep_s,
# axis_thru_rods = 'x',
# axis_thru_hole = 'y',
# name = 'cagecube')
class Lb1cPlate (object):
"""
Creates a LB1C/M plate from thorlabs. The plate is centered
fc_axis_l: axis on the large separation
|
|
:-- sy_hole_sep -:
: :
:cbore_hole_sep_s:
: : : :
_______________________
| O O | -------------------
| 0 0 | .... :
| | : :
| | : :
| ( ) | +sym_hole_sep + cbore_hole_sep_l
| | : :
| 0 0 | .... :
| O O | -------------------
|______________________|
________________________
| :: : ::..: | fc_axis_h
|__::___H______________| if ref_in=1 | -> h=0
________________________ if ref_in=0 -> h=0
| :: : ::..: | |
|__::___H______________| V fc_axis_h
Args
d_plate: dictionary with the dimensions
fc_axis_h: FreeCAD.Vector on the direction of the vertical (thickness)
fc_axis_l: FreeCAD.Vector on the direction of the large distance of
the counterbored asymetrical holes
ref_in: 1: fc_axis_h starts on the inside to outside of the plate
0: fc_axis_h starts on the outside to inside of the plate
pos : position of the center. FreeCAD.Vector. The center is on the
center of the plate, but on the axis_h can be in either side
depending on ref_in
name: name
"""
def __init__ (self, d_plate,
fc_axis_h = VZ,
fc_axis_l = VX,
ref_in = 1,
pos = V0,
name = 'lb1c_plate'):
doc = FreeCAD.ActiveDocument
# dictionary with the dimensions
self.d_plate = d_plate
side_l = d_plate['L']
thick = d_plate['thick']
sym_hole_d = d_plate['sym_hole_d']
sym_hole_sep = d_plate['sym_hole_sep']
cbore_hole_d = d_plate['cbore_hole_d']
cbore_hole_head_d =d_plate['cbore_hole_head_d']
cbore_hole_head_l =d_plate['cbore_hole_head_l']
cbore_hole_sep_l =d_plate['cbore_hole_sep_l']
cbore_hole_sep_s =d_plate['cbore_hole_sep_s']
# normalize de axis
axis_h = DraftVecUtils.scaleTo(fc_axis_h,1)
axis_l = DraftVecUtils.scaleTo(fc_axis_l,1)
axis_s = fc_axis_l.cross(fc_axis_h)
shp_box = fcfun.shp_box_dir(side_l, side_l, thick, axis_h, axis_l,
cw = 1, cd = 1, ch = 0,
pos = pos)
if ref_in == 1:
# the holes mounting hole (center) and the cap holes will start
# on the other side, and will go on negated axis_h.
# For the other holes (thruholes) it doesn't matter
pos_h_add = DraftVecUtils.scale(axis_h, thick)
axis_hole = DraftVecUtils.neg(axis_h)
# for the ring:
axis_ring = axis_h
pos_ring = pos + DraftVecUtils.scale(axis_h,
- d_plate['seal_ring_thick'] )
else:
pos_h_add = V0
axis_hole = axis_h
axis_ring = DraftVecUtils.neg(axis_h)
pos_ring = pos + DraftVecUtils.scale(axis_h,
thick + d_plate['seal_ring_thick'] )
shp_cenhole = fcfun.shp_cylcenxtr(r=d_plate['mhole_d']/2.,
h=d_plate['mhole_depth'],
normal=axis_hole,
ch = 0,
xtr_top=0, xtr_bot=1,
pos=pos + pos_h_add)
# Retaining ring hole
shp_ringhole = fcfun.shp_cylholedir (
r_out = ( d_plate['seal_ring_d']/2.
+ d_plate['seal_ring_thick']/2.),
r_in = ( d_plate['seal_ring_d']/2.
- d_plate['seal_ring_thick']/2.),
h = 2 * d_plate['seal_ring_thick'],
normal = axis_ring,
pos = pos_ring)
holes = [shp_ringhole]
# symetrical holes
for add_l in (DraftVecUtils.scaleTo(axis_l, sym_hole_sep/2),
DraftVecUtils.scaleTo(axis_l, - sym_hole_sep/2)) :
for add_s in (DraftVecUtils.scaleTo(axis_s, sym_hole_sep/2),
DraftVecUtils.scaleTo(axis_s, - sym_hole_sep/2)) :
pos_hole = pos + add_l + add_s
shp_hole = fcfun.shp_cylcenxtr(r=sym_hole_d/2., h=thick,
normal=axis_h,
ch = 0,
xtr_top=1., xtr_bot=1.,
pos=pos_hole)
holes.append(shp_hole)
# asymetrical hole
for add_l in (DraftVecUtils.scaleTo(axis_l, cbore_hole_sep_l/2),
DraftVecUtils.scaleTo(axis_l, - cbore_hole_sep_l/2)) :
for add_s in (DraftVecUtils.scaleTo(axis_s, cbore_hole_sep_s/2),
DraftVecUtils.scaleTo(axis_s, - cbore_hole_sep_s/2)) :
pos_hole = pos + add_l + add_s
shp_hole = fcfun.shp_cylcenxtr(r=cbore_hole_d/2., h=thick,
normal=axis_h,
ch = 0,
xtr_top=1., xtr_bot=1.,
pos=pos_hole)
shp_hole_head = fcfun.shp_cylcenxtr(r=cbore_hole_head_d/2.,
h=cbore_hole_head_l,
normal=axis_hole,
ch = 0,
xtr_top=0, xtr_bot=1,
pos=pos_hole + pos_h_add)
shp_cbore_hole = shp_hole.fuse(shp_hole_head)
holes.append(shp_cbore_hole)
shp_holes = shp_cenhole.multiFuse(holes)
shp_plate = shp_box.cut(shp_holes)
doc.recompute()
fco_plate = doc.addObject("Part::Feature", name )
fco_plate.Shape = shp_plate
self.fco = fco_plate
def color (self, color = (1,1,1)):
self.fco.ViewObject.ShapeColor = color
#doc = FreeCAD.newDocument()
#doc = FreeCAD.ActiveDocument
#Lb1cPlate (kcomp_optic.LB1CM_PLATE)
#Lb1cPlate (kcomp_optic.LB1CM_PLATE,
# fc_axis_h = VY,
# fc_axis_l = VXN,
# ref_in = 0,
# pos = V0)
def plate_thruhole_hole8 (side_l,
thick,
thruhole_d,
sym_hole_d,
sym_hole_sep,
cbore_hole_d,
cbore_hole_head_d,
cbore_hole_head_l,
cbore_hole_sep_l,
cbore_hole_sep_s,
fc_axis_h,
fc_axis_l,
cl=1, cw=1, ch=1,
pos = V0,
name = 'plate'):
"""
draws a square plate, with a thru-hole in the center.
4 sets of holes in symetrical positions for screws
4 sets of holes for cap-screws
fc_axis_l: axis on the large separation
|
|
:-- sy_hole_sep -:
: :
:cbore_hole_sep_s:
: : : :
_______________________
| O O | -------------------
| 0 .... 0 | .... :
| / \ | : :
| | | | : :
| | | | +sym_hole_sep + cbore_hole_sep_s
| \ .... / | : :
| 0 0 | .... :
| O O | -------------------
|______________________|
Arguments:
side_l: length of the plate (two sides)
thick : thickness (height of the plate)
thruhole_d: diamenter of the central hole
sym_hole_d: diamenter of the symetrical holes
sym_hole_sep: distance between the centers of the symetrical holes
cbore_hole_d: diameter of the shank of the counter bored hole
cbore_hole_head_d: diameter of the cap of the counterbored screw
cbore_hole_head_l: length of the cap (head) of the counterbored screw
cbore_hole_sep_l: large separation of the counterbored holes
cbore_hole_sep_s: small separation of the counterbored holes
fc_axis_h: FreeCAD.Vector on the direction of the vertical (thickness)
from the inside of the plate
fc_axis_l: FreeCAD.Vector on the direction of the large distance of
the counterbored asymetrical holes
cl: 1: centered on the fc_axis_l direction
cw: 1: centered on the axis_small direction (perpendicular to fc_axis_l
and fc_axis_h)
ch: 1: centered on the vertical direction (thickness)
pos : position of the center. FreeCAD.Vector
name: name
"""
doc = FreeCAD.ActiveDocument
# normalize de axis
axis_h = DraftVecUtils.scaleTo(fc_axis_h,1)
axis_l = DraftVecUtils.scaleTo(fc_axis_l,1)
axis_s = fc_axis_l.cross(fc_axis_h)
shp_box = fcfun.shp_box_dir(side_l, side_l, thick, axis_h, axis_l,
cw = cl, cd = cw, ch = ch,
pos = pos)
# getting the offset of the center coordinates
if cl == 1:
l_0 = V0 # already centered
else:
l_0 = DraftVecUtils.scaleTo(axis_l, side_l/2.)
if cw == 1:
s_0 = V0
else:
s_0 = DraftVecUtils.scaleTo(axis_s, side_l/2.)
if ch == 1: # for the height, we want the lower side
h_0 = DraftVecUtils.scaleTo(axis_h, -thick/2.)
else:
h_0 = V0
pos_center = pos + l_0 + s_0 + h_0
shp_cenhole = fcfun.shp_cylcenxtr(r=thruhole_d/2., h=thick,
normal=axis_h,
ch = 0,
xtr_top=1., xtr_bot=1.,
pos=pos_center)
# symetrical holes
holes = []
for add_l in (DraftVecUtils.scaleTo(axis_l, sym_hole_sep/2),
DraftVecUtils.scaleTo(axis_l, - sym_hole_sep/2)) :
for add_s in (DraftVecUtils.scaleTo(axis_s, sym_hole_sep/2),
DraftVecUtils.scaleTo(axis_s, - sym_hole_sep/2)) :
pos_hole = pos_center + add_l + add_s
shp_hole = fcfun.shp_cylcenxtr(r=sym_hole_d/2., h=thick,
normal=axis_h,
ch = 0,
xtr_top=1., xtr_bot=1.,
pos=pos_hole)
holes.append(shp_hole)
# asymetrical hole
for add_l in (DraftVecUtils.scaleTo(axis_l, cbore_hole_sep_l/2),
DraftVecUtils.scaleTo(axis_l, - cbore_hole_sep_l/2)) :
for add_s in (DraftVecUtils.scaleTo(axis_s, cbore_hole_sep_s/2),
DraftVecUtils.scaleTo(axis_s, - cbore_hole_sep_s/2)) :
pos_hole = pos_center + add_l + add_s
shp_hole = fcfun.shp_cylcenxtr(r=cbore_hole_d/2., h=thick,
normal=axis_h,
ch = 0,
xtr_top=1., xtr_bot=1.,
pos=pos_hole)
pos_head = ( pos_hole
+ DraftVecUtils.scaleTo(axis_h, thick-cbore_hole_head_l))
shp_hole_head = fcfun.shp_cylcenxtr(r=cbore_hole_head_d/2.,
h=cbore_hole_head_l,
normal=axis_h,
ch = 0,
xtr_top=1., xtr_bot=0,
pos=pos_head)
shp_cbore_hole = shp_hole.fuse(shp_hole_head)
holes.append(shp_cbore_hole)
shp_holes = shp_cenhole.multiFuse(holes)
shp_plate = shp_box.cut(shp_holes)
#doc.recompute()
#fco_plate = doc.addObject("Part::Feature", name )
#fco_plate.Shape = shp_plate
#return (fco_plate)
return (shp_plate)
# def BasePlace (self, position = (0,0,0)):
# self.base_place = position
# self.fco.Placement.Base = FreeCAD.Vector(position)
def plate_lb2c (
fc_axis_h,
fc_axis_l,
cl=1, cw=1, ch=0,
pos = V0,
name = 'lb2c_plate'):
shp_plate = plate_thruhole_hole8 (
side_l = kcomp_optic.LB2C_PLATE['L'], # 76.2,
thick = kcomp_optic.LB2C_PLATE['thick'],
thruhole_d = kcomp_optic.LB2C_PLATE['thruhole_d'],
sym_hole_d = kcomp_optic.LB2C_PLATE['sym_hole_d'],
sym_hole_sep = kcomp_optic.LB2C_PLATE['sym_hole_sep'],
cbore_hole_d = kcomp_optic.LB2C_PLATE['cbore_hole_d'],
cbore_hole_head_d = kcomp_optic.LB2C_PLATE['cbore_hole_head_d'],
cbore_hole_head_l = kcomp_optic.LB2C_PLATE['cbore_hole_head_l'],
cbore_hole_sep_l = kcomp_optic.LB2C_PLATE['cbore_hole_sep_l'],
cbore_hole_sep_s = kcomp_optic.LB2C_PLATE['cbore_hole_sep_s'],
fc_axis_h = fc_axis_h,
fc_axis_l = fc_axis_l,
cl=cl, cw=cw, ch=ch,
pos = pos,
name = name)
return shp_plate
#doc = FreeCAD.newDocument()
#doc = FreeCAD.ActiveDocument
#plate_lb2c (fc_axis_h = VZ, fc_axis_l = VX, cl=1, cw=1, ch=0, pos=V0,
# name = 'lb2c_plate')