-
Notifications
You must be signed in to change notification settings - Fork 0
/
Points2Circle.py
145 lines (110 loc) · 3.99 KB
/
Points2Circle.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
#***************************************************
# Points to Circle (COFFEE)
# David Wickenden 2007
# converted to Python - Daniel Sterckx 14-sept-2018
#***************************************************
import c4d
def main():
radius = 50 # enter radius here
if not op : return
if not op.IsInstanceOf(c4d.Opolygon) : return
doc.StartUndo()
# step 1
# we convert the selected points to edges
# from the edges we create a spline
settings = c4d.BaseContainer();
settings[c4d.MDATA_CONVERTSELECTION_LEFT] = 0
settings[c4d.MDATA_CONVERTSELECTION_RIGHT] = 1
res = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_CONVERTSELECTION,
list = [op],
mode = c4d.MODIFY_POINTSELECTION,
bc = settings,
doc = doc,
flags = c4d.MODELINGCOMMANDFLAGS_0)
if res is False:
print "P2C: Failed convert points to edges."
return
res = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_EDGE_TO_SPLINE,
list = [op],
mode = c4d.MODIFY_EDGESELECTION,
bc = settings,
doc = doc,
flags = c4d.MODELINGCOMMANDFLAGS_CREATEUNDO)
if res is False:
print "P2C: Failed edge to spline."
return
# step 2
# we get the spline to process it
spline = op.GetDown();
if not spline:
print "P2C: Failed to get the spline."
return;
if spline.IsInstanceOf(c4d.Opolygon) : return
pointCnt = op.GetPointCount()
pointSel = op.GetPointS()
pointSelCnt = pointSel.GetCount()
spPointCnt = spline.GetPointCount()
spPointSel = spline.GetPointS()
spPointSelCnt = spPointSel.GetCount()
if spPointCnt != pointSelCnt: return
# step 3
# map the points of the spline to the original points
# of the object, in order to be able to move the appropriate ones later
pointMap = []
sel = pointSel.GetAll(pointCnt)
for pIndex, selected in enumerate(sel):
if not selected: continue
# find the matching point in the spline
for spIndex in xrange(spPointCnt):
if op.GetPoint(pIndex) == spline.GetPoint(spIndex):
data = (pIndex, spIndex)
pointMap.append(data)
break
# display the result (debug)
#for m in pointMap:
# print m[0], m[1]
# step 4
# make the spline into a circle
# apply the spline coordinates to the appropriate source points
doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
vectorSum = c4d.Vector(0)
for i in xrange(spPointCnt):
p = spline.GetPoint(i)
vectorSum += spline.GetPoint(i)
spMg = spline.GetMg()
vectorAv = vectorSum / spPointCnt
vectorAv_g = spMg.Mul(vectorAv)
refPointA = spline.GetPoint(0)
refPointB = spline.GetPoint(1)
refPointAg = spMg.Mul(refPointA)
refPointBg = spMg.Mul(refPointB)
m = c4d.Matrix()
m.off = vectorAv_g
m.v1 = (refPointAg - vectorAv_g).GetNormalized()
mV1 = m.v1
m.v3 = mV1.Cross((refPointBg - vectorAv_g).GetNormalized())
mV3 = m.v3
m.v2 = mV3.Cross(mV1).GetNormalized()
angle = 6.283 / spPointCnt
opMg = op.GetMg();
mInv = ~m;
opMgInv = ~opMg
for pm in pointMap:
pointA = spline.GetPoint(pm[1])
pointAg = spMg.Mul(pointA)
pointAl = mInv.Mul(pointAg)
sn, cs = c4d.utils.SinCos(angle * (pm[1]))
posAl_x = cs * radius;
posAl_y = sn * radius;
pointAlMod = c4d.Vector(posAl_x, posAl_y, pointAl.z)
pointAg2 = m.Mul(pointAlMod)
pointAl2 = opMgInv.Mul(pointAg2)
op.SetPoint(pm[0], pointAl2)
spline.Remove()
op.Message(c4d.MSG_UPDATE)
#c4d.CallCommand(200000089) # Scale
doc.EndUndo()
c4d.EventAdd()
return
if __name__=='__main__':
main()