enum AdjustType { NoAdjust, AdjustVertex, AdjustEdge, DiagonalFold, ArrangeAngle }; class Adjust{ public: AdjustType type; Vertex *markVertex[2]; Edge *markEdge; double margin; double marginAngle; void clear(){ type = NoAdjust; } Adjust(){ this->clear(); margin = 0.5; marginAngle = 5.0; } bool adjustVertex(class Stage &stage){ Vertex *closest; double distance; stage.fold.pickedFaceGroup()->closestVertex( stage.fold.destination, closest, distance ); if( distance < margin ){ type = AdjustVertex; markVertex[0] = closest; stage.fold.update( closest->position ); return true; } return false; } bool correctBend(class Stage &stage){ double angle = stage.fold.angle; if ( fabs(deg(angle)-90.0) < marginAngle ){ angle = rad(90.0); type = ArrangeAngle; } else if( fabs(deg(angle)+90.0) < marginAngle ){ angle = -rad(90.0); type = ArrangeAngle; } else if( fabs(deg(angle)-45.0) < marginAngle ){ angle = rad(45.0); type = ArrangeAngle; } else if( fabs(deg(angle)+45.0) < marginAngle ){ angle = -rad(45.0); type = ArrangeAngle; } if( type == ArrangeAngle ){ Vector destination; destination.rotate( stage.fold.vertex->position, stage.fold.axis, angle ); stage.fold.update( destination ); return true; } return false; } bool adjustDiagonal(class Stage &stage){ Vertex *closest[2]; double distance[2]; stage.fold.faceGroup->closestVertex( stage.fold.axis, closest[0], distance[0] ); stage.fold.faceGroup->closestVertex( stage.fold.axis, closest[1], distance[1], closest[0]->position ); if( distance[0] < margin && distance[1] < margin ){ type = DiagonalFold; Line adjustAxis( closest[0]->position, closest[1]->position ); if( stage.fold.axis.direction * adjustAxis.direction < 0.0 ) adjustAxis.direction = - adjustAxis.direction; Vector destination; destination.rotate( stage.fold.vertex->position, adjustAxis, stage.fold.angle ); for(int i=0; i<2; i++) markVertex[i] = closest[i]; stage.fold.update( destination ); return true; } return false; } bool adjustEdge(class Stage &stage){ Face **pickedFaceList = stage.fold.faceGroup->pickedFaceList( *stage.fold.vertex ); Vertex *pickedVertex = stage.fold.vertex; FaceGroup *pickedFaceGroup = stage.fold.faceGroup; int f = 0; while( pickedFaceList[f] != NULL ){ Edge *pickedEdge[2], *closestEdge[2]; double distance[2]; Vector rotatedPosition[2][2]; for(int e=0; e<2; e++){ pickedEdge[e] = pickedFaceList[f]->neighborEdge( *pickedVertex, e ); for(int v=0; v<2; v++) rotatedPosition[e][v] = stage.fold.rotateVertexPosition( pickedEdge[e]->vertex[v]->position ); closestEdge[e] = pickedFaceGroup->closestEdge( distance[e], rotatedPosition[e][0], rotatedPosition[e][1] ); } if( distance[0] < margin || distance[1] < margin ){ type = AdjustEdge; Line line[2]; int e = distance[0] < distance[1] ? 0 : 1; line[0].set( pickedEdge[e]->vertex[0]->position, pickedEdge[e]->vertex[1]->position ); line[1].set( closestEdge[e]->vertex[0]->position, closestEdge[e]->vertex[1]->position ); Vector v = rotatedPosition[e][1] -rotatedPosition[e][0]; if( line[1].direction * ( v ) < 0.0 ) line[0].direction = - line[0].direction; markEdge = pickedEdge[e]; if( line[1].direction.angle( line[0].direction ) > 3.14*0.9 ){ stage.fold.destination.projection( line[1] ); }else{ Line axis; axis.equidistance( line[0], line[1] ); stage.fold.destination.rotate( stage.fold.vertex->position, axis, stage.fold.angle ); } stage.fold.update(); return true; } f++; } delete pickedFaceList; return false; } void correctDestination(Stage &stage){ type=NoAdjust; if( Key.down('f') ) return; if( this->adjustVertex( stage ) ) return; if( stage.fold.isBend() && this->correctBend( stage ) ) return; if( this->adjustDiagonal( stage ) ) return; if( this->adjustEdge( stage ) ) return; } void draw(double radius = 0.3){ glColor3ub(255, 255, 0); switch( type ){ case AdjustVertex: markVertex[0]->position._glutSolidSphere(radius, 8, 8); break; case AdjustEdge: if( markEdge->label == DividedEdge ){ if( markEdge->children[0]->label == MovedEdge ){ markVertex[0] = markEdge->children[0]->vertex[0]; markVertex[1] = markEdge->children[0]->vertex[1]; }else{ markVertex[0] = markEdge->children[1]->vertex[0]; markVertex[1] = markEdge->children[1]->vertex[1]; } }else{ markVertex[0] = markEdge->vertex[0]; markVertex[1] = markEdge->vertex[1]; } markVertex[0]->position._glutSolidSphere(radius, 8, 8); markVertex[1]->position._glutSolidSphere(radius, 8, 8); break; case DiagonalFold: markVertex[0]->position._glutSolidSphere(radius, 8, 8); markVertex[1]->position._glutSolidSphere(radius, 8, 8); break; } } };