ofVec3f SteeringBehaviors::Cohesion(const std::vector<Vehicle*>&_neighbors) { ofVec3f _steeringForce(0.0, 0.0, 0.0); ofVec3f CenterOfMass(0.0, 0.0, 0.0); int NeighborCount = 0; for (int a = 0; a < _neighbors.size(); ++a) { //make sure this agent isn't included in the calculations and that //the agent being examined is close enough. ***also make sure it doesn't //include the evade target *** if ((_neighbors[a] != m_Vehicle) && (_neighbors[a]->IsTagged()) && (_neighbors[a] != m_Vehicle->Target())) { CenterOfMass += _neighbors[a]->Pos(); ++NeighborCount; } } if (NeighborCount > 0) { CenterOfMass /= NeighborCount; _steeringForce = Seek(CenterOfMass); } return(_steeringForce.getNormalized()); }
ofVec3f SteeringBehaviors::CohesionPlus(const std::vector<Vehicle*>&_neighbors) { ofVec3f CenterOfMass(0.0,0.0,0.0); ofVec3f _steeringForce(0.0, 0.0, 0.0); int NeighborCount = 0; //iterate through the neighbors and sum up all the position vectors for (BaseEntity* pV = m_Vehicle->GameWorld()->CellSpace()->begin(); !m_Vehicle->GameWorld()->CellSpace()->end(); pV = m_Vehicle->GameWorld()->CellSpace()->next()) { //make sure this agent isn't included in the caclulations and that the agent being examined is close enough if (pV != m_Vehicle) { CenterOfMass += pV->Pos(); ++NeighborCount; } } if (NeighborCount > 0) { CenterOfMass /= NeighborCount; _steeringForce = Seek(CenterOfMass); } return (_steeringForce.getNormalized()); }
void vtkKMeansClustering::EstimateClusterCenters(vtkPoints* data, vtkPoints* clusterCenters) { vtkSmartPointer<vtkPoints> oldCenters = vtkSmartPointer<vtkPoints>::New(); oldCenters->ShallowCopy(clusterCenters); clusterCenters->Reset(); clusterCenters->Squeeze(); for(unsigned int cluster = 0; cluster < this->K; cluster++) { vtkSmartPointer<vtkPoints> classPoints = vtkSmartPointer<vtkPoints>::New(); for(unsigned int point = 0; point < data->GetNumberOfPoints(); point++) { if(this->Labels[point] == cluster) { classPoints->InsertNextPoint(data->GetPoint(point)); } } double center[3]; if(classPoints->GetNumberOfPoints() == 0) { //GetRandomPoint(data, center); oldCenters->GetPoint(cluster, center); } else { CenterOfMass(classPoints, center); } clusterCenters->InsertNextPoint(center); } }
void sdgEngine::Explode(float factor) { double com[3]; //residue center-of-mass CenterOfMass(_atoms, com); MIAtom_const_iter i, e = _atoms.end(); for (i = _atoms.begin(); i != e; ++i) { (*i)->setPosition( (float)(com[0] + factor * ((*i)->x() - com[0])), (float)(com[1] + factor * ((*i)->y() - com[1])), (float)(com[2] + factor * ((*i)->z() - com[2]))); } }
vnl_double_3x3 SampleCovarianceMatrix(const std::vector<vgl_point_3d<double> > &Points) { vgl_point_3d<double> u = CenterOfMass(Points); vnl_double_3x3 S; S.fill(0); for(unsigned int i = 0; i < Points.size(); i++) { vgl_vector_3d<double> V = Points[i] - u; vnl_double_3x3 OP = VXLHelpers::OuterProduct(V, V); S += OP; } S /= Points.size(); return S; }
vgl_plane_3d<double> BestPlane(const std::vector<vgl_point_3d<double> > &Points) { //this function finds the eigen vector corresponding to the smallest eigen value and places the plane's P0 at the center of mass of the points. vgl_point_3d<double> Centroid = CenterOfMass(Points); vnl_double_3x3 S = SampleCovarianceMatrix(Points); std::vector<vnl_double_3> evecs = VXLHelpers::EigenVectors(S); std::vector<vgl_vector_3d<double> > EvecsVGL; for(unsigned int i = 0; i < 3; i++) EvecsVGL.push_back(VXLHelpers::vnl_vector_to_vgl_vector(evecs[i])); //WriteEigenVectorVTP(Centroid, EvecsVGL, .3); vgl_plane_3d<double> P(EvecsVGL[0], Centroid); //apparently these are sorted from smallest to largest? return P; }
int NS_DIM_PREFIX BalanceGridRCB (MULTIGRID *theMG, int level) { HEAP *theHeap = theMG->theHeap; GRID *theGrid = GRID_ON_LEVEL(theMG,level); /* balance grid of level */ LB_INFO *lbinfo; ELEMENT *e; int i, son; INT MarkKey; /* distributed grids cannot be redistributed by this function */ if (me!=master && FIRSTELEMENT(theGrid) != NULL) { printf("Error: Redistributing distributed grids using recursive coordinate bisection is not implemented!\n"); return (1); } if (me==master) { if (NT(theGrid) == 0) { UserWriteF("WARNING in BalanceGridRCB: no elements in grid\n"); return (1); } Mark(theHeap,FROM_TOP,&MarkKey); lbinfo = (LB_INFO *) GetMemUsingKey(theHeap, NT(theGrid)*sizeof(LB_INFO), FROM_TOP, MarkKey); if (lbinfo==NULL) { Release(theHeap,FROM_TOP,MarkKey); UserWrite("ERROR in BalanceGridRCB: could not allocate memory from the MGHeap\n"); return (1); } /* construct LB_INFO list */ for (i=0, e=FIRSTELEMENT(theGrid); e!=NULL; i++, e=SUCCE(e)) { lbinfo[i].elem = e; CenterOfMass(e, lbinfo[i].center); } /* apply coordinate bisection strategy */ theRCB(lbinfo, NT(theGrid), 0, 0, DimX, DimY, 0); IFDEBUG(dddif,1) for (e=FIRSTELEMENT(theGrid); e!=NULL; e=SUCCE(e)) { UserWriteF("elem %08x has dest=%d\n", DDD_InfoGlobalId(PARHDRE(e)), PARTITION(e)); } ENDDEBUG for (i=0, e=FIRSTELEMENT(theGrid); e!=NULL; i++, e=SUCCE(e)) { InheritPartition (e); } Release(theHeap,FROM_TOP,MarkKey); } return 0; }
// // LATER: remove printfs... // // main tracking function. Processes a given sequence of type YARPImageSequence. int YARPFlowTracker::Apply (YARPOutputPortOf<YARPGenericImage>& port) { printf ("ox %d oy %d\n", ox, oy); // PROCESSING SEQUENCE. int start = seq->GetStartPushing(); int stop = seq->GetStopPushing(); printf ("Processing from frame %d to %d\n", start, stop); printf ("Sequence has %d frames\n", seq->GetNumElements()); assert (stop-start+1 <= m_maxsize); // PREPARE SEQUENCE FOR PROCESSING. processor.Reset (); oseq.Reset (); contact = 0; contact_frame = 0; howmanycontacts = 0; lack_of_vectors = 0; int i, frame; for (frame = start; frame <= stop; frame++) { oseq.IncrementCounter (); contact = processor.Apply (seq->GetImageRef (frame), oseq.GetImageRef (frame-start)); oseq.GetImageRef (frame-start) = seq->GetImageRef (frame); if (contact) { processor.GetPokeDirection (dirx, diry); processor.GetSegmentedImage (segmentation_mask); segmentation_mask_copy = segmentation_mask; processor.GetFlipper(flipper_segmentation_mask); flipper_segmentation_mask_copy = flipper_segmentation_mask; ba.Apply(segmentation_mask_copy); orientation = ba.GetAngle(); orientation_quality = ba.GetPointiness(); // enlarge it twice. GrowMask (segmentation_mask, extended_segmentation); segmentation_mask = extended_segmentation; GrowMask (segmentation_mask, extended_segmentation); CenterOfMass (extended_segmentation, com_x, com_y); contact_frame = frame; howmanycontacts++; GenerateAndSend (port); } } if (howmanycontacts == 0) { printf ("No poking detected... \n"); // nothing much to do. return -1; } // OPTICFLOW. int startopticflow = contact_frame - 5; //10; if (startopticflow < start) startopticflow = start; int endopticflow = contact_frame + FRAMES_TRACKED; if (endopticflow > stop) endopticflow = stop; // TRACK. int endtracking = contact_frame+FRAMES_TRACKED; if (endtracking > stop) endtracking = stop; // optic flow mask, initialize optic flow and additional tracker. mask.Zero(); YARPColorConverter::RGB2Grayscale (seq->GetImageRef(startopticflow), mono); of.Initialize (mono); bool trackvalid = false; int sx = com_x, sy = com_y; int sx2 = com_x, sy2 = com_y; tracker.Initialize (seq->GetImageRef(startopticflow), com_x, com_y); YarpPixelBGR green; green.r = green.b = 0; green.g = 0; i = 0; for (frame = startopticflow+1; frame <= endopticflow; frame++) { AddCircleOutline (oseq.GetImageRef(frame-start+1), green, sx, sy, 10); if (tracker.IsTracking()) { tracker.Apply (seq->GetImageRef(frame), true, sx2, sy2, trackvalid); printf ("frame: %d, valid: %d, sx, sy: %d %d\n", frame, trackvalid, sx2, sy2); } YARPColorConverter::RGB2Grayscale (seq->GetImageRef(frame), mono); if (frame < contact_frame) of.Apply (mono, mask, sx2-sx, sy2-sy, outimage, vx[frame-start], vy[frame-start]); else of.Apply (mono, extended_segmentation, sx2-sx, sy2-sy, outimage, vx[frame-start], vy[frame-start]); sx = sx2; sy = sy2; of.DrawFlow (oseq.GetImageRef (frame-start)); if (frame == contact_frame) WriteMask (extended_segmentation, oseq.GetImageRef (frame-start)); if (frame >= contact_frame+1 && frame <= endtracking) { if (ComputeRotation (extended_segmentation, vx[frame-start], vy[frame-start], ox, oy, trsf[i], 10) == -2) lack_of_vectors++; i++; WriteMask (extended_segmentation, oseq.GetImageRef (frame-start)); } } CenterOfMass (extended_segmentation, final_x, final_y); printf ("starting point: %d %d\n", com_x, com_y); printf ("center of mass: %d %d\n", final_x, final_y); dispframe = contact_frame - start - 10; // it was -5. m_stepping = 2; if (lack_of_vectors > 6) { printf ("optic flow is poor, skipping frames\n"); oseq.Reset (); // adjust start frame parity. int newstart = start; if (((contact_frame % 2) == 0 && (newstart % 2) == 1) || ((contact_frame % 2) == 1 && (newstart % 2) == 0) ) newstart ++; lack_of_vectors = 0; printf ("re-processing from frame %d to %d\n", start, stop); // RECOMPUTING INDEX ETC. // segmentation_mask = segmentation_mask_copy; flipper_segmentation_mask = flipper_segmentation_mask_copy; // enlarge it twice. GrowMask (segmentation_mask, extended_segmentation); segmentation_mask = extended_segmentation; GrowMask (segmentation_mask, extended_segmentation); // contact frame is ok. // poke dir is ok. // center of mass is ok. // RECOMPUTE OPTIC FLOW. int startopticflow = contact_frame - 10; //20; if (startopticflow < newstart) startopticflow = newstart; if (((contact_frame % 2) == 0 && (startopticflow % 2) == 1) || ((contact_frame % 2) == 1 && (startopticflow % 2) == 0) ) startopticflow ++; int endopticflow = contact_frame + FRAMES_TRACKED*2; if (endopticflow > stop) endopticflow = stop; // TRACK. int endtracking = contact_frame+FRAMES_TRACKED*2; if (endtracking > stop) endtracking = stop; YARPColorConverter::RGB2Grayscale (seq->GetImageRef(startopticflow), mono); of.Initialize (mono); bool trackvalid = false; int sx = com_x, sy = com_y; int sx2 = com_x, sy2 = com_y; tracker.Initialize (seq->GetImageRef(startopticflow), com_x, com_y); YarpPixelBGR green; green.r = green.b = 0; green.g = 0; for (frame = start; frame <= stop; frame++) { oseq.IncrementCounter (); oseq.GetImageRef (frame-start) = seq->GetImageRef (frame); } i = 0; for (frame = startopticflow+2; frame <= endopticflow; frame+=2) { AddCircleOutline (oseq.GetImageRef(frame-start+2), green, sx, sy, 10); if (tracker.IsTracking()) { tracker.Apply (seq->GetImageRef(frame), true, sx2, sy2, trackvalid); printf ("frame: %d, valid: %d, sx, sy: %d %d\n", frame, trackvalid, sx2, sy2); } YARPColorConverter::RGB2Grayscale (seq->GetImageRef(frame), mono); if (frame < contact_frame) of.Apply (mono, mask, sx2-sx, sy2-sy, outimage, vx[frame-start], vy[frame-start]); else of.Apply (mono, extended_segmentation, sx2-sx, sy2-sy, outimage, vx[frame-start], vy[frame-start]); sx = sx2; sy = sy2; of.DrawFlow (oseq.GetImageRef (frame-start)); if (frame == contact_frame) WriteMask (extended_segmentation, oseq.GetImageRef (frame-start)); if (frame >= contact_frame+2 && frame <= endtracking) { if (ComputeRotation (extended_segmentation, vx[frame-start], vy[frame-start], ox, oy, trsf[i], 10) == -2) lack_of_vectors++; i++; WriteMask (extended_segmentation, oseq.GetImageRef (frame-start)); } } CenterOfMass (extended_segmentation, final_x, final_y); printf ("starting point: %d %d\n", com_x, com_y); printf ("center of mass: %d %d\n", final_x, final_y); printf ("improved? %d\n", lack_of_vectors); // // // m_stepping = 4; dispframe = contact_frame - start - 10; if (dispframe < 0) dispframe = 0; if (lack_of_vectors > 6) { // bad sequence. printf ("Still bad flow after post-processing\n"); return -2; } } return 0; }
//酸素の位置を読みこむ。 sLattIce* load_LattIce( FILE* file, real hposition ) { char buf[1000]; sLattIce* ice; bool coord=False, network=False; real rhb=0; ice = calloc( 1, sizeof( sLattIce ) ); ice->periodic = False; //ice->dryrun = False; /*プロトンの場所は不明*/ ice->currentBond = -1; ice->currentPotential = 0; while( NULL != fgets( buf, sizeof( buf ), file ) ){ if ( strncmp( buf, "@BOX3",5 ) == 0 ){ fgets( buf, sizeof( buf ), file ); ice->periodic = True; #ifdef SINGLEPRECISION sscanf( buf, "%f %f %f", &ice->bx, &ice->by, &ice->bz ); #else sscanf( buf, "%lf %lf %lf", &ice->bx, &ice->by, &ice->bz ); #endif } else if ( strncmp( buf, "@BXLA",5 ) == 0 ){ fgets( buf, sizeof( buf ), file ); ice->periodic = True; #ifdef SINGLEPRECISION sscanf( buf, "%f", &ice->bx ); #else sscanf( buf, "%lf", &ice->bx ); #endif ice->by = ice->bz = ice->bx; } else if ( strncmp( buf, "@NGPH", 5 ) == 0 ){ int o1,o2; int no; int nhb=0; network = True; fgets( buf, sizeof( buf ), file ); no = atoi( buf ); if ( ice->nOxygen == 0 ){ ice->nOxygen = no; ice->comx = ice->comy = ice->comz = 0; ice->oxygens = calloc( ice->nOxygen, sizeof( sOxygen ) ); ice->bonds = calloc( ice->nOxygen * 2, sizeof( sHydrogenBond ) ); } else if ( ice->nOxygen != no ){ fprintf( stderr, "Error: number of sites differ: %d != %d\n", ice->nOxygen, no ); exit(1); } /*ネットワークを読みこむ。一応有向グラフと考える。*/ while ( NULL != fgets( buf, sizeof( buf ), file ) ){ sOxygen* oxy1; sOxygen* oxy2; sHydrogenBond* hb; sscanf( buf, "%d %d", &o1, &o2 ); if ( o1 < 0 ) break; oxy1 = &ice->oxygens[ o1 ]; oxy2 = &ice->oxygens[ o2 ]; hb = &ice->bonds[ nhb ]; oxy1->hydrogenBond[ oxy1->nAdj ] = nhb; oxy1->oxygen[ oxy1->nAdj ] = o2; oxy2->hydrogenBond[ oxy2->nAdj ] = nhb; oxy2->oxygen[ oxy2->nAdj ] = o1; if ( o1 < o2 ){ hb->oxygen[0] = o1; hb->oxygen[1] = o2; hb->direction = +1; } else { hb->oxygen[0] = o2; hb->oxygen[1] = o1; hb->direction = -1; } oxy1->outgo ++; oxy1->nAdj ++; oxy2->nAdj ++; nhb ++; } ice->nBond = nhb; } else if ( strncmp( buf, "@PPOS", 5 ) == 0 ){ int o1,o2; int no; int nhb; sOxygen* oxy1; sOxygen* oxy2; sHydrogenBond* hb; /*@PPOSより前に@NGPHを読みこんでいる必要がある。*/ if ( ! network ){ fprintf( stderr, "Network topology must be read before proton position.\n" ); exit(1); } fgets( buf, sizeof( buf ), file ); no = atoi( buf ); /*ネットワークを読みこむ。一応有向グラフと考える。*/ nhb = ice->nBond; /*最初のプロトンしか読まない。*/ fgets( buf, sizeof( buf ), file ); sscanf( buf, "%d %d", &o1, &o2 ); oxy1 = &ice->oxygens[ o1 ]; oxy2 = &ice->oxygens[ o2 ]; hb = &ice->bonds[ nhb ]; oxy1->hydrogenBond[ oxy1->nAdj ] = nhb; oxy1->oxygen[ oxy1->nAdj ] = o2; oxy2->hydrogenBond[ oxy2->nAdj ] = nhb; oxy2->oxygen[ oxy2->nAdj ] = o1; hb->oxygen[0] = o1; hb->oxygen[1] = o2; hb->direction = 0; oxy1->nAdj ++; oxy2->nAdj ++; ice->currentBond = nhb; nhb ++; ice->nBond = nhb; } else if ( strncmp( buf, "@RCOO", 5 ) == 0 ){ /*結合しているとみなすO-O間距離の閾値*/ fgets( buf, sizeof( buf ), file ); rhb = atof( buf ); } else if ( strncmp( buf, "@NX4A", 5 ) == 0 || strncmp( buf, "@AR3A", 5 ) == 0 || strncmp( buf, "@NX3A", 5 ) == 0 ){ int o1; int no; coord = True; fgets( buf, sizeof( buf ), file ); no = atoi( buf ); if ( ice->nOxygen == 0 ){ ice->nOxygen = no; ice->comx = ice->comy = ice->comz = 0; ice->oxygens = calloc( ice->nOxygen, sizeof( sOxygen ) ); ice->bonds = calloc( ice->nOxygen * 2, sizeof( sHydrogenBond ) ); } else if ( ice->nOxygen != no ){ fprintf( stderr, "Error: number of sites differ: %d != %d\n", ice->nOxygen, no ); exit(1); } /*座標を読みこむ。*/ for( o1=0; o1< ice->nOxygen; o1++ ){ fgets( buf, sizeof( buf ), file ); #ifdef SINGLEPRECISION sscanf( buf, "%f %f %f", &ice->oxygens[o1].x, &ice->oxygens[o1].y, &ice->oxygens[o1].z ); #elif real == double sscanf( buf, "%lf %lf %lf", &ice->oxygens[o1].x, &ice->oxygens[o1].y, &ice->oxygens[o1].z ); #else #error #endif /*ファイルから読む場合はとりあえずダミーサイトではないと考える。→平成16年2月18日(水)変更。結合数によってダミーかどうかを決める。*/ ice->oxygens[o1].charge = -2; } #ifdef DEBUG fprintf( stderr, "CoM: %f %f %f\n", ice->comx, ice->comy, ice->comz ); #endif } //if ( coord && network ) break; } if ( ! network && 0.0 < rhb ) { DetermineBonds( ice, rhb ); } CenterOfMass( ice ); /*O-O間のプロトンのとりうる位置3つの座標を計算する。*/ SetHBins( ice, hposition ); return ice; //fprintf( stderr, "Error: No inputs.\n" ); //exit(1); }
/*create N x N x N cubic ice */ sLattIce* CubicIce( int n, real hposition ) { int x,y,z; int nhb; int o1; sLattIce* ice; ice = malloc( sizeof(sLattIce) ); ice->oxygens = calloc( n*n*n, sizeof( sOxygen ) ); ice->bonds = calloc( n*n*n*2, sizeof( sHydrogenBond ) ); ice->nOxygen = n*n*n; ice->periodic = False; //ice->dryrun = False; for ( x=0; x<2*n; x+=2 ){ for ( y=0; y<2*n; y+=2 ){ for ( z=0; z<2*n; z+=2 ){ if ( ( ( x+y+z ) % 4 ) == 0 ){ int xi,yi,zi; //位置から酸素IDを得る int self = Coordinate2OxygenID( n, x, y, z ); if ( ice->oxygens[self].x != 0 || ice->oxygens[self].y != 0 || ice->oxygens[self].z != 0 ){ printf("%d %d %d %d is used\n", self,x,y,z); } //位置を保存する ice->oxygens[self].x = x; ice->oxygens[self].y = y; ice->oxygens[self].z = z; //立方体表面にあるなら if ( x == 0 || x == 2*n-2 || y == 0 || y == 2*n-2 || z == 0 || z == 2*n-2 ) //ダミーサイトである。 ice->oxygens[self].charge = 0; else{ //水素の電荷の-2倍。 ice->oxygens[self].charge = -2; ice->oxygens[self].oxygen[0] = Coordinate2OxygenID( n, x+1, y+1, z+1 ); ice->oxygens[self].oxygen[1] = Coordinate2OxygenID( n, x+1, y-1, z-1 ); ice->oxygens[self].oxygen[2] = Coordinate2OxygenID( n, x-1, y+1, z-1 ); ice->oxygens[self].oxygen[3] = Coordinate2OxygenID( n, x-1, y-1, z+1 ); ice->oxygens[self].nAdj = 4; } xi = x + 1; yi = y + 1; zi = z + 1; self = Coordinate2OxygenID( n, xi, yi, zi ); ice->oxygens[self].x = xi; ice->oxygens[self].y = yi; ice->oxygens[self].z = zi; if ( xi == 2*n-1 || yi == 2*n-1 || zi == 2*n-1 ) ice->oxygens[self].charge = 0; else{ ice->oxygens[self].charge = -2; ice->oxygens[self].oxygen[0] = Coordinate2OxygenID( n, xi-1, yi-1, zi-1 ); ice->oxygens[self].oxygen[1] = Coordinate2OxygenID( n, xi-1, yi+1, zi+1 ); ice->oxygens[self].oxygen[2] = Coordinate2OxygenID( n, xi+1, yi-1, zi+1 ); ice->oxygens[self].oxygen[3] = Coordinate2OxygenID( n, xi+1, yi+1, zi-1 ); ice->oxygens[self].nAdj = 4; } } } } } CenterOfMass( ice ); /*つぎに水素結合を定義する。*/ nhb = 0; /*すべての酸素原子について*/ for ( o1=0; o1<n*n*n; o1++ ){ /*もしダミーサイト(表面サイト)でなければ*/ if ( ice->oxygens[o1].charge != 0 ){ int j; /*4つの隣接酸素について*/ for( j=0; j<ice->oxygens[o1].nAdj; j++ ){ int o2; o2 = ice->oxygens[o1].oxygen[j]; /*o1<o2なら、ボンドを登録する(重複登録をさけるため)*/ if ( o1 < o2 ) { /*bondの2つの端点を登録する*/ ice->bonds[nhb].oxygen[0] = o1; ice->bonds[nhb].oxygen[1] = o2; /*この結合をo2への結合として登録する。*/ ice->oxygens[o1].hydrogenBond[j] = nhb; /*隣接酸素がダミーサイトでないなら*/ if ( ice->oxygens[o2].charge != 0 ){ int k; /*隣接酸素の隣接酸素について*/ for ( k=0; k<ice->oxygens[o2].nAdj; k++ ) /*それがo1なら*/ if ( ice->oxygens[o2].oxygen[k] == o1 ) /*この結合をo2からo1への結合として登録する*/ ice->oxygens[o2].hydrogenBond[k] = nhb; } /*登録結合数を増やす*/ nhb ++; } /*隣接酸素がダミーサイトなら*/ else if ( ice->oxygens[o2].charge == 0 ) { /*o2 < o1でもボンドを登録する。*/ ice->bonds[nhb].oxygen[1] = o1; ice->bonds[nhb].oxygen[0] = o2; ice->oxygens[o1].hydrogenBond[j] = nhb; nhb ++; } } } } //結合総数には、ダミーボンドへの結合が含まれるので、酸素(電荷あり)の総数の2倍よりも大きいはず。 ice->nBond = nhb; SetHBins( ice, hposition ); return ice; }