/***********************************************************************
*
* ELMER, A Computational Fluid Dynamics Program.
*
* Copyright 1st April 1995 - , Center for Scientific Computing,
* Finland.
*
* All rights reserved. No part of this program may be used,
* reproduced or transmitted in any form or by any means
* without the written permission of CSC.
*
* Address: Center for Scientific Computing
* Tietotie 6, P.O. BOX 405
* 02101 Espoo, Finland
* Tel. +358 0 457 2001
* Telefax: +358 0 457 2302
* EMail: Jari.Jarvinen@csc.fi
************************************************************************/
/***********************************************************************
Program: ELMER Front
Module: ecif_body2D.cpp
Language: C++
Date: 01.10.98
Version: 1.00
Author(s): Martti Verho
Revisions:
Abstract: Implementation
************************************************************************/
#include "ecif_body2D.h"
#include "ecif_bodyElement.h"
#include "ecif_bodyElement2D.h"
#include "ecif_bodyElementLoop.h"
#include "ecif_model.h"
#include "ecif_renderer.h"
#include "ecif_userinterface.h"
// Constructors.
Body2D::Body2D()
: Body()
{
}
//--Body-elements etc are not known
Body2D::Body2D(bodyGmtrType body_type, int ext_tag, char* name, colorIndices color)
: Body(body_type, ext_tag, name, color)
{
}
//--Component ids are known, but not more.
Body2D::Body2D(ecif_Body_X& trx_body, bool add_default_layer)
: Body(trx_body, add_default_layer)
{
}
Body2D::Body2D(bodyGmtrType body_type, int int_tag, int ext_tag,
int nof_mesh_elements, int* mesh_element_ids)
:Body(body_type, int_tag, ext_tag, NULL)
{
maxNofMeshElements = nof_mesh_elements;
nofMeshElements = nof_mesh_elements;
meshElementIds = mesh_element_ids;
}
bool
Body2D::acceptsStructuredMesh(int layer)
{
if (!checkLayerIndex(layer)) return false;
// If more than one loops, no grid!
if ( nofElementLoops[layer] == 0 || nofElementLoops[layer] > 1 ) {
return false;
}
// If more or less than four elements, n grid!
if ( nofElements[layer] != 4 ) {
return false;
}
// Ok, gridable
return true;
}
// Add all pending vertices as elements
// Returns nof elements added
int
Body2D::addAllPendingVertices(int layer)
{
if (!checkLayerIndex(layer)) return 0;
int nof_vertex_tags = pendingVertexTags[layer]->size();
if ( nof_vertex_tags == 0 )
return 0;
// Vertex ids are stored in this table
// Allocate space also for the possible closing
// vetex
int* vertex_groups = new int[1 + nof_vertex_tags];
int* vertex_ids = new int[1 + nof_vertex_tags];
int nof_vertex_ids = 0;
int i;
for (i = 0; i < nof_vertex_tags; i++) {
// Read and remove last element
int v_group = (*pendingVertexGroups[layer])[i];
int v_tag = (*pendingVertexTags[layer])[i];
// Find vertex by tag and get id
BodyElement* v = model->getVertexByTag(v_tag);
if (v != NULL) {
vertex_groups[nof_vertex_ids] = v_group;
vertex_ids[nof_vertex_ids] = v->Id();
nof_vertex_ids++;
}
}
int nof_elements = 0;
int groupd_id = vertex_groups[0];
for (i = 1; i < nof_vertex_ids; i++) {
int v1 = vertex_ids[i-1];
int v2 = vertex_ids[i];
// Inside group, create new element
if ( groupd_id == vertex_groups[i] ) {
BodyElement* be = new BodyElement2D(v1, v2);
addElement(layer, be);
model->addBodyElement(be, false);
nof_elements++;
}
groupd_id = vertex_groups[i];
}
pendingVertexGroups[layer]->clear();
pendingVertexTags[layer]->clear();
return nof_elements;
}
#if 0
// Method checks that edges create a closed loop and it stores the
// edge-loop as table of consecutive edge-ids. A negative id-number
// in the table means that edge is in the reversed order.
// Return true if body is ok, otherwise false.
bool
Body2D::check()
{
checked = true;
bool result = false;
nofElements = belements->size();
if (nofElements == 0)
return false;
// A table where row is: (edge-id, vertex1-id, vertex2-id)
int (*vertex_table)[3] = new int[nofElements][3];
BodyElement* be;
BodyElement* vertex;
int e_id, v1_id, v2_id;
BodyElementTable::iterator pos = belements->begin();
// Now the (edge,vertex1,vertex2)-table is filled.
int row = 0;
while (pos != belements->end()) {
be = (*pos++).second;
e_id = be->ID();
vertex = be->getSubElement(1);
v1_id = vertex->ID();
vertex = be->getSubElement(2);
v2_id = vertex->ID();
vertex_table[row][0] = e_id;
vertex_table[row][1] = v1_id;
vertex_table[row][2] = v2_id;
row++;
}
// Next we create a edgeLoop-table which is simply a list of edge-id
// numbers. A negative id-number in the table means that edge's
// vertices are in opposite order compared to whole loop order.
IdList* edgeLoop = new IdList;
// Starting edge is selcted.
int table_row = 0;//we take the first edge as a staring edge.
int vrtx_nbr = 1;
// These are needed to check at the end that loop is closed.
int start_vertex = vertex_table[0][1];
int end_vertex = vertex_table[0][2];
// OUTER LOOP: once for each edge in the resulting edge-loop table.
for (int i = 0; i < nofElements; i++) {
// order of vertices compared to whole loop order
int sign = (vrtx_nbr == 1)? 1: -1;
edgeLoop->push_back(sign * vertex_table[table_row][0]);
// id for the other vertex in the edge's vertex pair.
// Next edge is
int v_id = vertex_table[table_row][(vrtx_nbr==1)?2:1];
end_vertex = v_id;
// we don't want to search for this table-row any more, lets mark it off!
vertex_table[table_row][0] *= -1;
// now next row in *vertex_table* is searhced.
// Note: updating of *vrtx_nbr* is based on short-circuit property
// of the logical operators in C++!!
// INNER LOOP: we search for the 'next' edge in the (edge,vrtx1,vrtx2)-table
for (int j = 0; j < nofElements; j++) {
vrtx_nbr = 1;
if ( (vertex_table[j][0] > 0)
&&
// here short-circuit is used in logical-or (||) when
// vtrx_nbr is selcted based on first matching column.
(vertex_table[j][vrtx_nbr] == v_id ||
vertex_table[j][++vrtx_nbr] == v_id )) {
table_row = j;
break;
}
}
}
if (start_vertex == end_vertex)
result = true;
else
return false;
// If we have a closed loop of edges, we can create the final
// element-loop to be stored in the Model.
// We also ccheck loops ccw/cw orientation
int loopDirection;
BodyElementLoop* bel;
if (result == true) {
bel = new BodyElementLoop(edgeLoop);
model->addBodyElementLoop(bel);
elementLoopIds->push_back(bel->ID());
loopDirection = calcDirection();
}
// If for some reason edge-loop orientation couldn't
// be calulated, status is not ok.
if (loopDirection == 0)
result = false;
// If loop direction was clock-wise, we have to
// change the loop-ids sign to indicate this
else if (loopDirection < 0) {
elementLoopIds->pop_back();
elementLoopIds->push_back(-1 * bel->ID());
}
return result;
}
#endif
// New version checking all element-loops defined for the body
// Method checks that edges create a closed loop and it stores the
// edge-loop as table of consecutive edge-ids. A negative id-number
// in the table means that edge is in the reversed order.
// Return true if body is ok, otherwise false.
bool
Body2D::check()
{
if (nofLayers == 0) return false;
initName();
// For a mesh, open or virtual body
// ================================
if ( isMeshBody() ||
isBemBody() ||
isOpen() ||
isVirtual()
) {
return Body::check();
}
// For a closed cad body
// =====================
UserInterface* gui = (UserInterface*)model->getGui();
// Check all layers
// ----------------
int layer = -1;
while (true) {
if (!selectLayer(++layer)) break;
int nof_pending_vertices = addAllPendingVertices(layer);
int nof_pending_elements = addAllPendingElements(layer);
checked = true;
nofElements[layer] = belements[layer]->size();
if ( nofElements[layer] == 0 ) {
// We have elementLoops constructed already,
// Store element ids from the loop to the belements-array
if ( nofElementLoops[layer] > 0 ) {
if ( !addAllLoopElements(layer) ) {
status = false;
return false;
}
nofElements[layer] = belements[layer]->size();
// All input loops were checked (emf-file!), the body
// shoud be ok
if ( nof_pending_elements == 0 && status == true ) {
continue;
}
// We have neither elements nor elementLoops,
// something is really wrong!
} else {
strstream strm1, strm2;
strm1 << "***ERROR in geometry for Body " << tag << ":" << ends;
strm2 << "---No Edges or Edge Loops defined!" << ends;
gui->showMsg(strm1.str());
gui->showMsg(strm2.str(), 1);
status = false;
return false;
}
}
// Construct loops from "scratch"
// ==============================
//--Remove existing loops
removeElementLoops(layer);
status = false;
//--Create a table where rows are: (edge-id, vertex1-id, vertex2-id)
int (*vertex_table)[3] = new int[nofElements[layer]][3];
BodyElement* edge;
BodyElement* vertex;
int e_id, v1_id, v2_id;
BodyElementTable::iterator pos = belements[layer]->begin();
int row = 0;
//--Fill the table.
while ( pos != belements[layer]->end() ) {
edge = (*pos++).second;
e_id = edge->Id();
// If no vertices in the element or we have a closed element like
// a circle
if ( edge->isClosedU() || edge->getNofSubElements() == 0 ) {
v1_id = 0;
v2_id = 0;
} else {
v1_id = edge->getFirstSubElement()->Id();
v2_id = edge->getLastSubElement()->Id();
}
vertex_table[row][0] = e_id;
vertex_table[row][1] = v1_id;
vertex_table[row][2] = v2_id;
row++;
}
// Next we create a edgeLoop-table which is simply a list of edge-id
// numbers. A negative id-number in the table means that edge's
// vertices are in opposite order compared to whole loop order.
// Starting edge for the loop is selected.
int nof_free_elements = nofElements[layer];
while (nof_free_elements > 0) {
// OUTERMOST For: once for each edge in the resulting edge-loop table.
for (int k = 0; k < nofElements[layer]; k++) {
if (vertex_table[k][0] < 0)
continue;
IdList edge_loop;
int table_row = k;//we take the first free edge as the starting edge.
int vrtx_nbr = 1;
// These are needed to finally check that the element loop is closed.
int start_vertex, end_vertex;
start_vertex = vertex_table[k][1];
end_vertex = -1;
while (nof_free_elements > 0 && start_vertex != end_vertex) {
// OUTER For: once for each edge in the resulting edge-loop table.
for (int i = 0; i < nofElements[layer]; i++) {
if ( vertex_table[i][0] < 0 ) continue;
// Order of vertices compared to whole loop order
int sign = (vrtx_nbr == 1)? 1: -1;
// Add new edge
edge_loop.push_back(sign * vertex_table[table_row][0]);
nof_free_elements--;
// We don't want to search for this table-row any more, lets mark it off!
vertex_table[table_row][0] *= -1;
// Id for the other vertex in the edge's vertex pair.
int v_id = vertex_table[table_row][(vrtx_nbr==1)?2:1];
end_vertex = v_id;
if (start_vertex == end_vertex) break;
// Now next row in *vertex_table* is searhced.
// Note: updating of *vrtx_nbr* is based on short-circuit property
// of the logical operators in C!!
// INNER For: we search for the 'next' edge in the (edge,vrtx1,vrtx2)-table
for (int j = 0; j < nofElements[layer] ; j++) {
if (vertex_table[j][0] < 0) continue;
vrtx_nbr = 1;
// NOTE: Here short-circuit is used in logical-or (||) when
// vtrx_nbr is selcted based on first matching column.
if (vertex_table[j][vrtx_nbr] == v_id ||
vertex_table[j][++vrtx_nbr] == v_id ) {
table_row = j;
break;
}
} // End INNER For
if (nof_free_elements <= 0 ) break;
} // End OUTER For
} // End OUTER While
// We could not close the loop, error!
if (start_vertex != end_vertex) {
strstream strm;
strm << "***ERROR in geometry for Body " << tag << " in layer "
<< layer + 1 << ends;
gui->showMsg(strm.str());
gui->showMsg("---Body not closed!", 1);
return false;
}
// All but the first loops are cw-directed
int loop_direction = ( nofElementLoops[layer] > 0 )?-1:1;
BodyElementLoop* bel = NULL;
int bel_id;
int direction; // Direction relative to the possible existing loop
//-Existing loop, just pick id and relative direction
//-NOTE All loops are stored in ccw-direction in the model, so
// we do not use the 'direction' argument here
//
if ( model->getBodyElementLoopId(&edge_loop, bel_id, direction) ) {
bel = model->getBodyElementLoopById(bel_id);
if ( bel == NULL ) return false;
//-Otherwise create new loop and add to the model
//
} else {
bel = new BodyElementLoop(&edge_loop, false, OT_BOUNDARY);
bel->check();
model->addBodyElementLoop(bel);
}
// Add loop id to the body
elementLoopIds[layer]->push_back(loop_direction * bel->Id());
elementLoopTags[layer]->push_back(bel->Tag());
nofElementLoops[layer]++;
// No more free edges
if (nof_free_elements <= 0) break;
} // End OUTERMOST For
} // End OUTERMOST While
} // Each body grid layer
status = true;
return true;
}
syntax highlighted by Code2HTML, v. 0.9.1