-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathSelNearDupCrvs.py
More file actions
119 lines (108 loc) · 4.79 KB
/
SelNearDupCrvs.py
File metadata and controls
119 lines (108 loc) · 4.79 KB
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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Finds and selects "near-duplicate" curves within a user-set tolerance.
Currently there is a bug in CurveDeviation (GetDistancesBetweenCurves)
that makes it unreliable... So this script instead uses first a
bounding box check, then length check, then divides curve and checks individual
point deviations. Short-circuit logic if one of the tests fail. Status bar
indicator for progress, can be long with large numbers of curves.
Script by Mitch Heynick 24.10.17
Revised - added optional arguments - and localized FR/EN 03.11.17
Minor adaptation 11.07.19: time rounded to 0.01 sec., default sampling set to 25
To do: revise with an rTree? Separate out polylines as different procedure?"""
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino, clr, System, time
import Rhino.RhinoMath as rm
def Localize(local_id):
#pass rs.LocaleID() as argument
msgs=[]
if local_id==1036:
msgs.append("Sélectionner les courbes à analyser")
msgs.append("Tolérance de sélection")
msgs.append("Calcul...")
msgs.append("Calcul")
msgs.append("Temps écoulé: {:.2f}")
msgs.append("{} courbes quasi-doublons trouvées")
msgs.append("Aucun quasi-doublon trouvé dans la tolérance choisi")
else:
msgs.append("Select curves to process")
msgs.append("Selection tolerance")
msgs.append("Working...")
msgs.append("Processing")
msgs.append("Elapsed time: {:.2f}")
msgs.append("{} near duplicate curves found")
msgs.append("No near duplicates found within tolerance")
return msgs
def PC(): return Rhino.Runtime.HostUtils.RunningOnWindows
def IsNearDupCrv(ref_crv,test_crv,user_tol,divs=5):
#ref_crv, test_crv are tuples: [0]=crv,[1]=bb,[2]=len
if ref_crv[1].Max.EpsilonEquals(test_crv[1].Max,user_tol):
if ref_crv[1].Min.EpsilonEquals(test_crv[1].Min,user_tol):
#bounding box within tolerance, test overall length
if rm.EpsilonEquals(ref_crv[2],test_crv[2],user_tol):
#length within tolerance, divide ref. curve by a # of points
pt_cont=clr.StrongBox[System.Array[Rhino.Geometry.Point3d]]()
div=ref_crv[0].DivideByCount(divs,True,pt_cont)
#check point deviation at each point
if div:
#pt_cont.Value is list of points on ref_crv
for pt in pt_cont.Value:
rc,p=test_crv[0].ClosestPoint(pt)
if rc:
if pt.DistanceTo(test_crv[0].PointAt(p))>user_tol:
#at least one point is too far, jump out
return
return True
#can adapt sampling (crv_divs)
def SelectNearDupCrvs(chk_all=True,sel_dup_all=False,crv_divs=25,user_tol=0.1):
msgs=Localize(rs.LocaleID())
if chk_all:
crvIDs=rs.ObjectsByType(4,state=1)
else:
crvIDs=rs.GetObjects(msgs[0],4,preselect=True)
if not crvIDs: return
if "SelNearDup_Tol" in sc.sticky: user_tol = sc.sticky["SelNearDup_Tol"]
tol=sc.doc.ModelAbsoluteTolerance
comp_tol=rs.GetReal(msgs[1],user_tol,minimum=tol)
if comp_tol is None: return
crv_bbs=[]
for crvID in crvIDs:
crv=sc.doc.Objects.Find(crvID).Geometry
bb=crv.GetBoundingBox(True)
length=crv.GetLength()
crv_bbs.append((crv,bb,length))
rs.EnableRedraw(False)
rs.Prompt(msgs[2])
if PC: rs.StatusBarProgressMeterShow(msgs[3],0,100,True)
#idea - collect indices, not IDs...
found_index=set()
st=time.time()
for i in range(len(crv_bbs)-1):
if PC and i % 100 ==0:
rs.StatusBarProgressMeterUpdate(100*i/len(crv_bbs))
for j in range(i+1,len(crv_bbs)):
#check to see if cuve is already in select list
if j in found_index: continue
#print "Compare curve {} to curve {}".format(i,j)
if IsNearDupCrv(crv_bbs[i],crv_bbs[j],comp_tol,crv_divs):
found_index.add(j)
if sel_dup_all: found_index.add(i)
if PC: rs.StatusBarProgressMeterHide()
print msgs[4].format(time.time()-st)
if found_index:
#need to add list of IDs
found=[crvIDs[index] for index in found_index]
rs.SelectObjects(found)
msg=msgs[5].format(len(found))
else:
msg=msgs[6]
print msg
sc.sticky["SelNearDup_Tol"] = comp_tol
"""optional arguments:
chk_all - True==check all visible selectable curves; False==user select curves
sel_dup_all - True==select all duplicates, False==leave one duplicate unselected
crv_divs - number of points to sample along curve
user_tol - default comparison tolerance (user-adaptable, sticky)
Defaults: True, False, 25, 0.1 """
SelectNearDupCrvs()