ExclusionPolygon::ExclusionPolygon(PassOwnPtr<Vector<FloatPoint> > vertices, WindRule fillRule) : ExclusionShape() , m_vertices(vertices) , m_fillRule(fillRule) { unsigned nVertices = numberOfVertices(); m_edges.resize(nVertices); m_empty = nVertices < 3; if (nVertices) m_boundingBox.setLocation(vertexAt(0)); if (m_empty) return; unsigned minVertexIndex = 0; for (unsigned i = 1; i < nVertices; ++i) { const FloatPoint& vertex = vertexAt(i); if (vertex.y() < vertexAt(minVertexIndex).y() || (vertex.y() == vertexAt(minVertexIndex).y() && vertex.x() < vertexAt(minVertexIndex).x())) minVertexIndex = i; } FloatPoint nextVertex = vertexAt((minVertexIndex + 1) % nVertices); FloatPoint prevVertex = vertexAt((minVertexIndex + nVertices - 1) % nVertices); bool clockwise = determinant(vertexAt(minVertexIndex) - prevVertex, nextVertex - prevVertex) > 0; unsigned edgeIndex = 0; unsigned vertexIndex1 = 0; do { m_boundingBox.extend(vertexAt(vertexIndex1)); unsigned vertexIndex2 = findNextEdgeVertexIndex(vertexIndex1, clockwise); m_edges[edgeIndex].polygon = this; m_edges[edgeIndex].vertexIndex1 = vertexIndex1; m_edges[edgeIndex].vertexIndex2 = vertexIndex2; m_edges[edgeIndex].edgeIndex = edgeIndex; edgeIndex++; vertexIndex1 = vertexIndex2; } while (vertexIndex1); if (edgeIndex > 3) { const ExclusionPolygonEdge& firstEdge = m_edges[0]; const ExclusionPolygonEdge& lastEdge = m_edges[edgeIndex - 1]; if (areCollinearPoints(lastEdge.vertex1(), lastEdge.vertex2(), firstEdge.vertex2())) { m_edges[0].vertexIndex1 = lastEdge.vertexIndex1; edgeIndex--; } } m_edges.resize(edgeIndex); m_empty = m_edges.size() < 3; if (m_empty) return; for (unsigned i = 0; i < m_edges.size(); i++) { ExclusionPolygonEdge* edge = &m_edges[i]; m_edgeTree.add(EdgeInterval(edge->minY(), edge->maxY(), edge)); } }
unsigned ExclusionPolygon::findNextEdgeVertexIndex(unsigned vertexIndex1, bool clockwise) const { unsigned nVertices = numberOfVertices(); unsigned vertexIndex2 = nextVertexIndex(vertexIndex1, nVertices, clockwise); while (vertexIndex2 && areCoincidentPoints(vertexAt(vertexIndex1), vertexAt(vertexIndex2))) vertexIndex2 = nextVertexIndex(vertexIndex2, nVertices, clockwise); while (vertexIndex2) { unsigned vertexIndex3 = nextVertexIndex(vertexIndex2, nVertices, clockwise); if (!areCollinearPoints(vertexAt(vertexIndex1), vertexAt(vertexIndex2), vertexAt(vertexIndex3))) break; vertexIndex2 = vertexIndex3; } return vertexIndex2; }
int CXXSurface::upLoadSphere(CXXSphereElement &theSphere, double probeRadius, const int sense){ int oldVertexCount; CXXCoord theCentre = theSphere.centre(); vector<int, CXX::CXXAlloc<int> > equivalence(theSphere.nVertices()); vector<int, CXX::CXXAlloc<int> > uniqueAndDrawn(theSphere.nVertices()); int nDrawn = 0; for (unsigned i=0; i< theSphere.nVertices(); i++){ CXXCoord comp1(theSphere.vertex(i).vertex()); uniqueAndDrawn[i] = 0; if (theSphere.vertex(i).doDraw()){ uniqueAndDrawn[i] = 1; if (uniqueAndDrawn[i]){ equivalence[i] = nDrawn++; } } } static const std::string vertexName("vertices"); static const std::string accessiblesName("accessibles"); static const std::string normalsName("normals"); { oldVertexCount = numberOfVertices(); vertices.resize(oldVertexCount+nDrawn); int verticesHandle = getVectorHandle(vertexName); int accessiblesHandle = getVectorHandle(accessiblesName); int normalsHandle = getVectorHandle(normalsName); int iDraw = 0; for (unsigned int i=0; i< theSphere.nVertices(); i++){ if (uniqueAndDrawn[i]){ CXXCoord vertexCoord = theSphere.vertex(i).vertex(); if (sense == CXXSphereElement::Contact){ vertices[oldVertexCount+iDraw].setCoord(accessiblesHandle, vertexCoord); CXXCoord normal = vertexCoord - theCentre; CXXCoord diff(normal); diff *= (theSphere.radius() - probeRadius) / theSphere.radius(); normal.normalise(); vertices[oldVertexCount+iDraw].setCoord(normalsHandle, normal); CXXCoord vertex = theCentre + diff; vertices[oldVertexCount+iDraw].setCoord(verticesHandle, vertex); } else if (sense == CXXSphereElement::Reentrant) { vertices[oldVertexCount+iDraw].setCoord(verticesHandle, vertexCoord); CXXCoord normal = theCentre - vertexCoord; normal.normalise(); vertices[oldVertexCount+iDraw].setCoord(normalsHandle, normal); vertices[oldVertexCount+iDraw].setCoord(accessiblesHandle, theCentre); } else if (sense == CXXSphereElement::VDW) { vertices[oldVertexCount+iDraw].setCoord(verticesHandle, vertexCoord); CXXCoord normal = vertexCoord - theCentre; normal.normalise(); vertices[oldVertexCount+iDraw].setCoord(normalsHandle, normal); vertices[oldVertexCount+iDraw].setCoord(accessiblesHandle, vertexCoord+normal); } else if (sense == CXXSphereElement::Accessible) { vertices[oldVertexCount+iDraw].setCoord(verticesHandle, vertexCoord); CXXCoord normal = vertexCoord - theCentre; normal.normalise(); vertices[oldVertexCount+iDraw].setCoord(normalsHandle, normal); vertices[oldVertexCount+iDraw].setCoord(accessiblesHandle, vertexCoord); } iDraw++; } } } //Add atom pointers to the surface { void *atomBuffer[nDrawn];// = new void*[nDrawn]; int iDraw = 0; for (unsigned int i=0; i< theSphere.nVertices(); i++){ if (uniqueAndDrawn[i]){ mmdb::PAtom anAtom; if ((anAtom = theSphere.vertex(i).getAtom())!=0 ){ atomBuffer[iDraw] = (void *) anAtom; } else atomBuffer[iDraw] = (void *) theSphere.getAtom(); iDraw++; } } updateWithPointerData(nDrawn, "atom", oldVertexCount, atomBuffer); //delete [] atomBuffer; } // Add triangles to surface { int triangleBuffer[theSphere.nFlatTriangles()*3];// = new int[theSphere.nFlatTriangles()*3]; int drawCount = 0; std::list<CXXSphereFlatTriangle, CXX::CXXAlloc<CXXSphereFlatTriangle> >::const_iterator trianglesEnd = theSphere.getFlatTriangles().end(); for (std::list<CXXSphereFlatTriangle, CXX::CXXAlloc<CXXSphereFlatTriangle> >::const_iterator triangle = theSphere.getFlatTriangles().begin(); triangle != trianglesEnd; ++triangle){ const CXXSphereFlatTriangle &theTriangle(*triangle); if (theTriangle.doDraw()){ if (sense == CXXSphereElement::Contact || sense == CXXSphereElement::VDW || sense == CXXSphereElement::Accessible){ for (unsigned int j=0; j<3; j++){ int index = equivalence[theTriangle[2-j]]; triangleBuffer[3*drawCount+j] = index + oldVertexCount; } } else { for (unsigned int j=0; j<3; j++){ int index = equivalence[theTriangle[j]]; triangleBuffer[3*drawCount+j] = index + oldVertexCount; } } drawCount++; } } extendTriangles(triangleBuffer, drawCount); //delete [] triangleBuffer; } return 0; }
/** * Returns whether this object has a valid shape * @returns True if the entire MeshObject may enclose * one or more volumes. */ bool MeshObject::hasValidShape() const { // May enclose volume if there are at // at least 4 triangles and 4 vertices (Tetrahedron) return (numberOfTriangles() >= 4 && numberOfVertices() >= 4); }
bool TissueState::exportToDbTables(const int ImageHeight, ofstream& framesFile, ofstream &verticesFile, ofstream &cellsFile, ofstream &ignoredCellsFile, ofstream &undirectedBondsFile, ofstream &directedBondsFile, unsigned long &lastVid, unsigned long &lastDbid, unsigned long &lastUbid) const { if(contains(Cell::VoidCellId)) { std::cout << "Found void cell id " << Cell::VoidCellId << " in frame " << _frameNumber << "!" << std::endl; return false; } // add data to frames table framesFile << _frameNumber << LogFile::DataSeparator << _time << '\n'; if(framesFile.bad()) { std::cout << "Error writing frame data!" << std::endl; return false; } // add data to vertex table and generate map: vertex pointer -> vid std::map<Vertex*,unsigned long> vertexPointerToVid; for(int i=0; i<numberOfVertices(); ++i) { Vertex *v = vertex(i); ++lastVid; vertexPointerToVid[v] = lastVid; // write data: verticesFile << _frameNumber << LogFile::DataSeparator << lastVid << LogFile::DataSeparator << v->r.x() << LogFile::DataSeparator << ImageHeight-1-v->r.y() << '\n'; if(verticesFile.bad()) { std::cout << "Error writing vertex data!" << std::endl; return false; } } // add data to cell table and generate map for bond sorting within cells std::map<DirectedBond*,DirectedBond*> leftBondSeenFromCellMap; // void cell cellsFile << _frameNumber << LogFile::DataSeparator << Cell::VoidCellId << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << -1 << LogFile::DataSeparator << -1 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << LogFile::DataSeparator << 0 << '\n'; // other cells for(TissueState::CellConstIterator it=beginCellIterator(); it!=endCellIterator(); ++it) { Cell *c = cell(it); for(unsigned int j=0; j<c->bonds.size(); ++j) { leftBondSeenFromCellMap[c->bonds[j]] = c->bonds[(j+1)%c->bonds.size()]; } // write data; revert signs of nematic xy components such that the values in the .dat files corresponds to a coordinate system with the y axis pointing upwards cellsFile << _frameNumber << LogFile::DataSeparator << c->id << LogFile::DataSeparator << (int)c->duringTransitionBefore << LogFile::DataSeparator << (int)c->duringTransitionAfter << LogFile::DataSeparator << c->daughter << LogFile::DataSeparator << c->r.x() << LogFile::DataSeparator << ImageHeight-1-c->r.y() << LogFile::DataSeparator << c->area << LogFile::DataSeparator << c->elongation.c1() << LogFile::DataSeparator << -c->elongation.c2() << LogFile::DataSeparator << c->polarityR.c1() << LogFile::DataSeparator << -c->polarityR.c2() << LogFile::DataSeparator << c->intIntensityR << LogFile::DataSeparator << c->polarityG.c1() << LogFile::DataSeparator << -c->polarityG.c2() << LogFile::DataSeparator << c->intIntensityG << LogFile::DataSeparator << c->polarityB.c1() << LogFile::DataSeparator << -c->polarityB.c2() << LogFile::DataSeparator << c->intIntensityB << '\n'; if(cellsFile.bad()) { std::cout << "Error writing cell data!" << std::endl; return false; } } // ignored cells for(set<CellIndex>::const_iterator it=_ignoredCells.begin(); it!=_ignoredCells.end(); ++it) { // write data: ignoredCellsFile << _frameNumber << LogFile::DataSeparator << *it << '\n'; if(ignoredCellsFile.bad()) { std::cout << "Error writing data for ignored cells!" << std::endl; return false; } } // add data to undirected bonds table and generate map: bond pointer -> dbid std::map<DirectedBond*,unsigned long> directedBondPointerToDbid; std::map<DirectedBond*,unsigned long> directedBondPointerToUbid; std::map<DirectedBond*,unsigned long> newConjBondDbids; std::map<DirectedBond*,DirectedBond*> newConjBondLeftOfConjBondAsSeenFromVoidCell; for(TissueState::BondConstIterator it=beginBondIterator(); it!=endBondIterator(); ++it) { DirectedBond *b = bond(it); ++lastDbid; directedBondPointerToDbid[b] = lastDbid; if(!b->conjBond) { ++lastDbid; newConjBondDbids[b] = lastDbid; // conj bond of bond left of conj bond seen from void cell Vertex *v = b->rightVertex; unsigned int i; for(i=0; i<v->bonds.size(); ++i) { if(v->bonds[i]==b) break; } if(i==v->bonds.size()) { std::cout << "TissueState::exportToDbTables: bond not found within rightVertex!" << std::endl; throw std::exception(); } DirectedBond *oneBondCwAtVertex = v->bonds[ (i+v->bonds.size()-1)%v->bonds.size() ]; Cell *c = oneBondCwAtVertex->cell; for(i=0; i<c->bonds.size(); ++i) { if(c->bonds[i]==oneBondCwAtVertex) break; } if(i==c->bonds.size()) { std::cout << "TissueState::exportToDbTables: bond not found within cell!" << std::endl; throw std::exception(); } DirectedBond *oneBondCwAtCell = c->bonds[ (i+c->bonds.size()-1)%c->bonds.size() ]; newConjBondLeftOfConjBondAsSeenFromVoidCell[b] = oneBondCwAtCell; } if((!b->conjBond) || (directedBondPointerToUbid.count(b->conjBond)==0)) { ++lastUbid; directedBondPointerToUbid[b] = lastUbid; undirectedBondsFile << _frameNumber << LogFile::DataSeparator << lastUbid << LogFile::DataSeparator << b->length << '\n'; if(undirectedBondsFile.bad()) { std::cout << "Error writing undirectedBond data!" << std::endl; return false; } } else { directedBondPointerToUbid[b] = directedBondPointerToUbid.at(b->conjBond); } } // add data to directed bonds table for(TissueState::BondConstIterator it=beginBondIterator(); it!=endBondIterator(); ++it) { DirectedBond *b = bond(it); if(b->conjBond) { directedBondsFile << _frameNumber << LogFile::DataSeparator << directedBondPointerToDbid.at(b) << LogFile::DataSeparator << directedBondPointerToDbid.at(b->conjBond) << LogFile::DataSeparator << directedBondPointerToUbid.at(b) << LogFile::DataSeparator << b->cell->id << LogFile::DataSeparator << vertexPointerToVid[b->rightVertex] << LogFile::DataSeparator << directedBondPointerToDbid.at(leftBondSeenFromCellMap.at(b)) << '\n'; if(directedBondsFile.bad()) { std::cout << "Error writing directedBond data!" << std::endl; return false; } } else { // add bond directedBondsFile << _frameNumber << LogFile::DataSeparator << directedBondPointerToDbid.at(b) << LogFile::DataSeparator << newConjBondDbids.at(b) << LogFile::DataSeparator << directedBondPointerToUbid.at(b) << LogFile::DataSeparator << b->cell->id << LogFile::DataSeparator << vertexPointerToVid[b->rightVertex] << LogFile::DataSeparator << directedBondPointerToDbid.at(leftBondSeenFromCellMap.at(b)) << '\n'; if(directedBondsFile.bad()) { std::cout << "Error writing directedBond data!" << std::endl; return false; } // add new conj bond DirectedBond *conjBondOfLeftBondAsSeenFromVoidCell = newConjBondLeftOfConjBondAsSeenFromVoidCell.at(b); if(newConjBondDbids.count(conjBondOfLeftBondAsSeenFromVoidCell)==0) { std::cout << "TissueState::exportToDbTables: Problem with margin bonds!" << std::endl; throw std::exception(); } directedBondsFile << _frameNumber << LogFile::DataSeparator << newConjBondDbids.at(b) << LogFile::DataSeparator << directedBondPointerToDbid.at(b) << LogFile::DataSeparator << directedBondPointerToUbid.at(b) << LogFile::DataSeparator << Cell::VoidCellId << LogFile::DataSeparator << vertexPointerToVid[b->leftVertex] << LogFile::DataSeparator << newConjBondDbids.at(conjBondOfLeftBondAsSeenFromVoidCell) << '\n'; if(directedBondsFile.bad()) { std::cout << "Error writing directedBond data!" << std::endl; return false; } } } return true; }