forked from sghr/iGeo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
I2DSurfaceFieldGeo.java
165 lines (135 loc) · 5.54 KB
/
I2DSurfaceFieldGeo.java
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
/*---
iGeo - http://igeo.jp
Copyright (c) 2002-2013 Satoru Sugihara
This file is part of iGeo.
iGeo is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, version 3.
iGeo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with iGeo. If not, see <http://www.gnu.org/licenses/>.
---*/
package igeo;
/**
2D vector filed defined by a NURBS surface.
@author Satoru Sugihara
*/
public class I2DSurfaceFieldGeo extends IFieldGeo implements I2DFieldI{
public ISurfaceI surface;
public ISurfaceI fieldSurface;
public I2DSurfaceFieldGeo(ISurfaceI srf, ISurfaceI fieldSrf){
surface = srf; fieldSurface = fieldSrf;
// default of 2D surface field is linear decay with zero threshold.
linearDecay(0);
}
/** get original field value out of curve parameter u */
public IVec2I get(IVecI pos, IVec2I uv){ return fieldSurface.pt(uv).to2d(); }
/** get original field value out of curve parameter u */
public IVec2I get(IVecI pos, IVecI vel, IVec2I uv){ return fieldSurface.pt(uv).to2d(); }
/** get 3D vector field value */
public IVec2I get(IVecI v){ return get(v,(IVecI)null); }
/** get 3D vector field value */
public IVec2I get(IVecI pos, IVecI vel){
//IVec2I uv = surface.uv(pos.to2d());
IVec2 uv = surface.uv(pos.to2d()).get();
double r = intensity;
if(decay == Decay.Linear){
double dist = surface.pt(uv).to2d().dist(pos.to2d());
if(dist >= threshold &&
(uv.x<=0||uv.y<=0||uv.x>=1.0||uv.y>=1.0)) return new IVec2(); // zero
//(uv.x<IConfig.parameterTolerance || uv.y<IConfig.parameterTolerance ||
//uv.x>1.0-IConfig.parameterTolerance || uv.y>1.0-IConfig.parameterTolerance)) // inside
//return new IVec2(); // zero
if(threshold>0) r *= (threshold-dist)/threshold;
}
else if(decay == Decay.Gaussian){
double dist = surface.pt(uv).to2d().dist(pos.to2d());
if(threshold>0) r *= Math.exp(-2*dist*dist/(threshold*threshold));
}
IVec2I vec = get(pos, vel, uv);
if(bidirectional && vec.get().dot(vel.to2d()) < 0){ r=-r; }
if(constantIntensity){
double len = vec.len();
if(len<IConfig.tolerance){ return vec.zero(); }
return vec.len(r);
}
return vec.mul(r);
/*
switch(decay){
case None:{
if(constantIntensity){
IVec2I vec = get(v,surface.uv(v.to2d()));
double len = vec.len();
if(len<IConfig.tolerance){ return vec.zero(); }
return vec.len(intensity);
}
return get(v,surface.uv(v.to2d())).mul(intensity); // need get() in case of ISurfaceR ?
}
case Linear:{
IVec2I uv = surface.uv(v.to2d());
double dist = surface.pt(uv).to2d().dist(v.to2d());
if(dist >= threshold) return new IVec2(); // zero
double r = intensity;
if(threshold>0) r *= (threshold-dist)/threshold;
if(constantIntensity){
IVec2I vec = get(v,uv);
double len = vec.len();
if(len<IConfig.tolerance){ return vec.zero(); }
return vec.len(r);
}
return get(v,uv).mul(r);
}
case Gaussian:{
IVec2I uv = surface.uv(v.to2d());
double dist = surface.pt(uv).to2d().dist(v.to2d());
double r = intensity;
if(threshold>0) r *= Math.exp(-2*dist*dist/(threshold*threshold));
if(constantIntensity){
IVec2I vec = get(v,uv);
double len = vec.len();
if(len<IConfig.tolerance){ return vec.zero(); }
return vec.len(r);
}
return get(v,uv).mul(r);
}
}
return null;
*/
}
/** if output vector is besed on constant length (intensity) or variable depending geometry when curve or surface tangent is used */
public I2DSurfaceFieldGeo constantIntensity(boolean b){ super.constantIntensity(b); return this; }
/** if bidirectional is on, field force vector is flipped when velocity of particle is going opposite */
public I2DSurfaceFieldGeo bidirectional(boolean b){ super.bidirectional(b); return this; }
/** set no decay */
public I2DSurfaceFieldGeo noDecay(){ super.noDecay(); return this; }
/** set linear decay; When distance is equal to threshold, output is zero.*/
public I2DSurfaceFieldGeo linearDecay(double threshold){
super.linearDecay(threshold); return this;
}
public I2DSurfaceFieldGeo linear(double threshold){
super.linear(threshold); return this;
}
/** set Gaussian decay; Threshold is used as double of standard deviation (when distance is eqaul to threshold, output is 13.5% of original).
*/
public I2DSurfaceFieldGeo gaussianDecay(double threshold){
super.gaussianDecay(threshold); return this;
}
public I2DSurfaceFieldGeo gaussian(double threshold){
super.gaussian(threshold); return this;
}
public I2DSurfaceFieldGeo gauss(double threshold){ super.gauss(threshold); return this; }
public I2DSurfaceFieldGeo threshold(double t){ super.threshold(t); return this; }
public I2DSurfaceFieldGeo intensity(double i){ super.intensity(i); return this; }
public void del(){
if(surface!=null && surface==fieldSurface){
if(surface instanceof IObject){ ((IObject)surface).del(); }
}
else{
if(surface!=null && surface instanceof IObject){ ((IObject)surface).del(); }
if(fieldSurface!=null && fieldSurface instanceof IObject){ ((IObject)fieldSurface).del(); }
}
}
}