~ubuntu-branches/ubuntu/trusty/yade/trusty

« back to all changes in this revision

Viewing changes to pkg/dem/Dem3DofGeom_FacetSphere.cpp

  • Committer: Package Import Robot
  • Author(s): Anton Gladky, cf3f8d9
  • Date: 2013-10-30 20:56:33 UTC
  • mfrom: (20.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20131030205633-1f01r7hjce17d723
Tags: 1.05.0-2
[cf3f8d9] Pass -ftrack-macro-expansion=0 only if gcc>=4.8. (Closes: #726009)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// © Václav Šmilauer <eudoxos@arcig.cz>
2
 
#include "Dem3DofGeom_FacetSphere.hpp"
3
 
#include<yade/pkg/common/Sphere.hpp>
4
 
#include<yade/pkg/common/Facet.hpp>
5
 
YADE_PLUGIN((Dem3DofGeom_FacetSphere)
6
 
        #ifdef YADE_OPENGL
7
 
                (Gl1_Dem3DofGeom_FacetSphere)
8
 
        #endif  
9
 
                (Ig2_Facet_Sphere_Dem3DofGeom));
10
 
 
11
 
CREATE_LOGGER(Dem3DofGeom_FacetSphere);
12
 
Dem3DofGeom_FacetSphere::~Dem3DofGeom_FacetSphere(){}
13
 
 
14
 
void Dem3DofGeom_FacetSphere::setTgPlanePts(const Vector3r& p1new, const Vector3r& p2new){
15
 
        TRVAR3(cp1pt,cp2rel,contPtInTgPlane2()-contPtInTgPlane1());     
16
 
        cp1pt=se31.orientation.conjugate()*(turnPlanePt(p1new,normal,se31.orientation*localFacetNormal)+contactPoint-se31.position);
17
 
        cp2rel=se32.orientation.conjugate()*Dem3DofGeom_SphereSphere::rollPlanePtToSphere(p2new,effR2,-normal);
18
 
        TRVAR3(cp1pt,cp2rel,contPtInTgPlane2()-contPtInTgPlane1());     
19
 
}
20
 
 
21
 
void Dem3DofGeom_FacetSphere::relocateContactPoints(const Vector3r& p1, const Vector3r& p2){
22
 
        //TRVAR2(p2.norm(),effR2);
23
 
        if(p2.squaredNorm()>pow(effR2,2)){
24
 
                setTgPlanePts(Vector3r::Zero(),p2-p1);
25
 
        }
26
 
}
27
 
 
28
 
Real Dem3DofGeom_FacetSphere::slipToDisplacementTMax(Real displacementTMax){
29
 
        //FIXME: not yet tested
30
 
        // negative or zero: reset shear
31
 
        if(displacementTMax<=0.){ setTgPlanePts(Vector3r(0,0,0),Vector3r(0,0,0)); return displacementTMax;}
32
 
        // otherwise
33
 
        Vector3r p1=contPtInTgPlane1(), p2=contPtInTgPlane2();
34
 
        Real currDistSq=(p2-p1).squaredNorm();
35
 
        if(currDistSq<pow(displacementTMax,2)) return 0; // close enough, no slip needed
36
 
        //Vector3r diff=.5*(sqrt(currDistSq)/displacementTMax-1)*(p2-p1); setTgPlanePts(p1+diff,p2-diff);
37
 
        Real scale=displacementTMax/sqrt(currDistSq); setTgPlanePts(scale*p1,scale*p2);
38
 
        return (displacementTMax/scale)*(1-scale);
39
 
}
40
 
 
41
 
CREATE_LOGGER(Ig2_Facet_Sphere_Dem3DofGeom);
42
 
bool Ig2_Facet_Sphere_Dem3DofGeom::go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){
43
 
        Facet* facet=static_cast<Facet*>(cm1.get());
44
 
        Real sphereRadius=static_cast<Sphere*>(cm2.get())->radius;
45
 
 
46
 
        // IGeomFunctor::go(cm1,cm2,state1,state2,shift2,force,c);
47
 
 
48
 
        #if 1
49
 
                /* new code written from scratch, to make sure the algorithm is correct; it is about the same speed 
50
 
                        as sega's algo below, but seems more readable to me.
51
 
                        The FACET_TOPO thing is still missing here but can be copied literally once it is tested */
52
 
                // begin facet-local coordinates
53
 
                        Vector3r cogLine=state1.ori.conjugate()*(state2.pos+shift2-state1.pos); // connect centers of gravity
54
 
                        //TRVAR4(state1.pos,state1.ori,state2.pos,cogLine);
55
 
                        Vector3r normal=facet->normal;
56
 
                        Real planeDist=normal.dot(cogLine);
57
 
                        if(planeDist<0){normal*=-1; planeDist*=-1; }
58
 
                        if(planeDist>sphereRadius && !c->isReal() && !force) { /* LOG_TRACE("Sphere too far ("<<planeDist<<") from plane"); */ return false;  }
59
 
                        Vector3r planarPt=cogLine-planeDist*normal; // project sphere center to the facet plane
60
 
                        Real normDotPt[3];
61
 
                        Vector3r contactPt(Vector3r::Zero());
62
 
                        for(int i=0; i<3; i++) normDotPt[i]=facet->ne[i].dot(planarPt-facet->vertices[i]);
63
 
                        short w=(normDotPt[0]>0?1:0)+(normDotPt[1]>0?2:0)+(normDotPt[2]>0?4:0);
64
 
                        //TRVAR4(planarPt,normDotPt[0],normDotPt[1],normDotPt[2]);
65
 
                        //TRVAR2(normal,cogLine);
66
 
                        //TRVAR3(facet->vertices[0],facet->vertices[1],facet->vertices[2]);
67
 
                        switch(w){
68
 
                                case 0: contactPt=planarPt; break; // inside triangle
69
 
                                case 1: contactPt=getClosestSegmentPt(planarPt,facet->vertices[0],facet->vertices[1]); break; // +-- (n1)
70
 
                                case 2: contactPt=getClosestSegmentPt(planarPt,facet->vertices[1],facet->vertices[2]); break; // -+- (n2)
71
 
                                case 4: contactPt=getClosestSegmentPt(planarPt,facet->vertices[2],facet->vertices[0]); break; // --+ (n3)
72
 
                                case 3: contactPt=facet->vertices[1]; break; // ++- (v1)
73
 
                                case 5: contactPt=facet->vertices[0]; break; // +-+ (v0)
74
 
                                case 6: contactPt=facet->vertices[2]; break; // -++ (v2)
75
 
                                case 7: throw logic_error("Impossible triangle intersection?"); // +++ (impossible)
76
 
                                default: throw logic_error("Nonsense intersection value!");
77
 
                        }
78
 
                        normal=cogLine-contactPt; // called normal, but it is no longer the facet's normal (for compat)
79
 
                        //TRVAR3(normal,contactPt,sphereRadius);
80
 
                        if(!c->isReal() && normal.squaredNorm()>sphereRadius*sphereRadius && !force) { /* LOG_TRACE("Sphere too far from closest point"); */ return false; } // fast test before sqrt
81
 
                        Real norm=normal.norm(); normal/=norm; // normal is unit vector now
82
 
                        Real penetrationDepth=sphereRadius-norm;
83
 
        #else
84
 
                /* This code was mostly copied from InteractingFacet2InteractinSphere4SpheresContactGeometry */
85
 
                // begin facet-local coordinates 
86
 
                        Vector3r contactLine=state1.ori.Conjugate()*(state2.pos+shift2-state1.pos);
87
 
                        Vector3r normal=facet->normal;
88
 
                        Real L=normal.Dot(contactLine); // height/depth of sphere's center from facet's plane
89
 
                        if(L<0){normal*=-1; L*=-1;}
90
 
                        if(L>sphereRadius && !c->isReal()) return false; // sphere too far away from the plane
91
 
 
92
 
                        Vector3r contactPt=contactLine-L*normal; // projection of sphere's center to facet's plane (preliminary contact point)
93
 
                        const Vector3r* edgeNormals=facet->ne; // array[3] of edge normals (in facet plane)
94
 
                        int edgeMax=0; Real distMax=edgeNormals[0].Dot(contactPt);
95
 
                        for(int i=1; i<3; i++){
96
 
                                Real dist=edgeNormals[i].Dot(contactPt);
97
 
                                if(distMax<dist){edgeMax=i; distMax=dist;}
98
 
                        }
99
 
                        //TRVAR2(distMax,edgeMax);
100
 
                        // OK, what's the logic here? Copying from IF2IS4SCG…
101
 
                        Real sphereRReduced=shrinkFactor*sphereRadius;
102
 
                        Real inCircleR=facet->icr-sphereRReduced;
103
 
                        Real penetrationDepth;
104
 
                        if(inCircleR<0){inCircleR=facet->icr; sphereRReduced=0;}
105
 
                        if(distMax<inCircleR){// contact with facet's surface
106
 
                                penetrationDepth=sphereRadius-L;        
107
 
                                normal.normalize();
108
 
                        } else { // contact with the edge
109
 
                                contactPt+=edgeNormals[edgeMax]*(inCircleR-distMax);
110
 
                                bool noVertexContact=false;
111
 
                                //TRVAR3(edgeNormals[edgeMax],inCircleR,distMax);
112
 
                                // contact with vertex no. edgeMax
113
 
                                // FIXME: this is the original version, but why (edgeMax-1)%3? IN that case, edgeNormal to edgeMax would never be tried
114
 
                                //    if     (contactPt.Dot(edgeNormals[        (edgeMax-1)%3])>inCircleR) contactPt=facet->vu[edgeMax]*(facet->vl[edgeMax]-sphereRReduced);
115
 
                                if     (contactPt.Dot(edgeNormals[        edgeMax      ])>inCircleR) contactPt=facet->vu[edgeMax]*(facet->vl[edgeMax]-sphereRReduced);
116
 
                                // contact with vertex no. edgeMax+1
117
 
                                else if(contactPt.Dot(edgeNormals[edgeMax=(edgeMax+1)%3])>inCircleR) contactPt=facet->vu[edgeMax]*(facet->vl[edgeMax]-sphereRReduced);
118
 
                                // contact with edge no. edgeMax
119
 
                                else noVertexContact=true;
120
 
                                normal=contactLine-contactPt;
121
 
                                #ifdef FACET_TOPO
122
 
                                        if(noVertexContact && facet->edgeAdjIds[edgeMax]!=Body::ID_NONE){
123
 
                                                // find angle between our normal and the facet's normal (still local coords)
124
 
                                                Quaternionr q; q.Align(facet->normal,normal); AngleAxisr aa(q);
125
 
                                                assert(aa.angle()>=0 && aa.angle()<=Mathr::PI);
126
 
                                                if(edgeNormals[edgeMax].Dot(aa.axis())<0) aa.angle()*=-1.;
127
 
                                                bool negFace=normal.Dot(facet->normal)<0; // contact in on the negative facet's face
128
 
                                                Real halfAngle=(negFace?-1.:1.)*facet->edgeAdjHalfAngle[edgeMax]; 
129
 
                                                if(halfAngle<0 && aa.angle()>halfAngle) return false; // on concave boundary, and if in the other facet's sector, no contact
130
 
                                                // otherwise the contact will be created
131
 
                                        }
132
 
                                #endif
133
 
                                //TRVAR4(contactLine,contactPt,normal,normal.norm());
134
 
                                //TRVAR3(se31.orientation*contactLine,se31.position+se31.orientation*contactPt,se31.orientation*normal);
135
 
                                Real norm=normal.norm(); normal/=norm;
136
 
                                penetrationDepth=sphereRadius-norm;
137
 
                                //TRVAR1(penetrationDepth);
138
 
                        }
139
 
                // end facet-local coordinates
140
 
        #endif
141
 
 
142
 
        if(penetrationDepth<0 && !c->isReal()) return false;
143
 
 
144
 
 
145
 
        shared_ptr<Dem3DofGeom_FacetSphere> fs;
146
 
        Vector3r normalGlob=state1.ori*normal;
147
 
        bool isNew=false;
148
 
        if(c->geom) fs=YADE_PTR_CAST<Dem3DofGeom_FacetSphere>(c->geom);
149
 
        else {
150
 
                // LOG_TRACE("Creating new Dem3DofGeom_FacetSphere");
151
 
                fs=shared_ptr<Dem3DofGeom_FacetSphere>(new Dem3DofGeom_FacetSphere());
152
 
                c->geom=fs;
153
 
                isNew=true;
154
 
                fs->effR2=sphereRadius-penetrationDepth;
155
 
                fs->refR1=-1; fs->refR2=sphereRadius;
156
 
                // postponed till below, to avoid numeric issues
157
 
                // see https://lists.launchpad.net/yade-dev/msg02794.html
158
 
                // since displacementN() is computed from fs->contactPoint,
159
 
                // it was returning something like +1e-16 at the very first step
160
 
                // when it was created ⇒ the constitutive law was erasing the
161
 
                // contact as soon as it was created.
162
 
                // fs->refLength=…
163
 
                fs->cp1pt=contactPt; // facet-local intial contact point
164
 
                fs->localFacetNormal=facet->normal;
165
 
                fs->cp2rel.setFromTwoVectors(Vector3r::UnitX(),state2.ori.conjugate()*(-normalGlob)); // initial sphere-local center-contactPt orientation WRT +x
166
 
                fs->cp2rel.normalize();
167
 
        }
168
 
        fs->se31=state1.se3; fs->se32=state2.se3; fs->se32.position+=shift2;
169
 
        fs->normal=normalGlob;
170
 
        fs->contactPoint=state2.pos+shift2+(-normalGlob)*(sphereRadius-penetrationDepth);
171
 
        // this refLength computation mimics what displacementN() does inside
172
 
        // displcementN will therefore return exactly zero at the step the contact
173
 
        // was created, which is what we want
174
 
        if(isNew) fs->refLength=(state2.pos+shift2-fs->contactPoint).norm();
175
 
        return true;
176
 
}
177
 
 
178
 
#ifdef YADE_OPENGL
179
 
 
180
 
        #include<yade/lib/opengl/OpenGLWrapper.hpp>
181
 
        #include<yade/lib/opengl/GLUtils.hpp>
182
 
 
183
 
        bool Gl1_Dem3DofGeom_FacetSphere::normal=false;
184
 
        bool Gl1_Dem3DofGeom_FacetSphere::rolledPoints=false;
185
 
        bool Gl1_Dem3DofGeom_FacetSphere::unrolledPoints=false;
186
 
        bool Gl1_Dem3DofGeom_FacetSphere::shear=false;
187
 
        bool Gl1_Dem3DofGeom_FacetSphere::shearLabel=false;
188
 
 
189
 
        void Gl1_Dem3DofGeom_FacetSphere::go(const shared_ptr<IGeom>& ig, const shared_ptr<Interaction>& ip, const shared_ptr<Body>& b1, const shared_ptr<Body>& b2, bool wireFrame){
190
 
                Dem3DofGeom_FacetSphere* fs = static_cast<Dem3DofGeom_FacetSphere*>(ig.get());
191
 
                const Se3r& se31=b1->state->se3,se32=b2->state->se3;
192
 
                const Vector3r& pos1=se31.position; const Vector3r& pos2=se32.position;
193
 
                const Quaternionr& ori1=se31.orientation; const Quaternionr& ori2=se32.orientation;
194
 
                const Vector3r& contPt=fs->contactPoint;
195
 
                
196
 
                if(normal){
197
 
                        GLUtils::GLDrawArrow(contPt,contPt+fs->refLength*fs->normal); // normal of the contact
198
 
                }
199
 
                // sphere center to point on the sphere
200
 
                if(rolledPoints){
201
 
                        //cerr<<pos1<<" "<<pos1+ori1*fs->cp1pt<<" "<<contPt<<endl;
202
 
                        GLUtils::GLDrawLine(pos1+ori1*fs->cp1pt,contPt,Vector3r(0,.5,1));
203
 
                        GLUtils::GLDrawLine(pos2,pos2+(ori2*fs->cp2rel*Vector3r::UnitX()*fs->effR2),Vector3r(0,1,.5));
204
 
                }
205
 
                // contact point to projected points
206
 
                if(unrolledPoints||shear){
207
 
                        Vector3r ptTg1=fs->contPtInTgPlane1(), ptTg2=fs->contPtInTgPlane2();
208
 
                        if(unrolledPoints){
209
 
                                //TRVAR3(ptTg1,ptTg2,ss->normal)
210
 
                                GLUtils::GLDrawLine(contPt,contPt+ptTg1,Vector3r(0,.5,1));
211
 
                                GLUtils::GLDrawLine(contPt,contPt+ptTg2,Vector3r(0,1,.5)); GLUtils::GLDrawLine(pos2,contPt+ptTg2,Vector3r(0,1,.5));
212
 
                        }
213
 
                        if(shear){
214
 
                                GLUtils::GLDrawLine(contPt+ptTg1,contPt+ptTg2,Vector3r(1,1,1));
215
 
                                if(shearLabel) GLUtils::GLDrawNum(fs->displacementT().norm(),contPt,Vector3r(1,1,1));
216
 
                        }
217
 
                }
218
 
        }
219
 
 
220
 
#endif
221