示例#1
0
void Tree::Trichotomise()	{

	double lengthbefore = GetLength();
	PolyNode* node = mRoot->down;
	if (node->next->next == node)	{
		if (!node->IsLeaf())	{
			node = node->next;
		}
		else	{
			if (node->next->IsLeaf())	{
				cerr << "error : cannot trichotomise a two species tree\n";
				exit(1);
			}
		}

		PolyNode* temp = node->next;
		node->Detach();
		// PolyNode* temp = mRoot->down;
		mRoot->down = 0;
		// delete mRoot;
		mRoot = temp;
		mRoot->up = 0;
		node->branchLength += mRoot->branchLength;
		mRoot->branchLength = 0;
		node->AttachTo(mRoot);
	}
	double lengthafter = GetLength();
	if (fabs(lengthafter - lengthbefore) > 1e-8)	{
		cerr << "error in trichotomise: length not conserved\n";
		cerr << "length before : " << lengthbefore << '\n';
		cerr << "length after  : " << lengthafter << '\n';
		cerr << lengthbefore - lengthafter << '\n';
		exit(1);
	}
}
示例#2
0
void
Tree::RootAt(PolyNode* inNode)	{

	double lengthbefore = GetLength();
	// inNode should not be root
	if (inNode->IsRoot())	{
		cerr << "error in PolyNode::RootAt : inNode is root\n";
		exit(1);
	}

	if (inNode)	{

		PolyNode* theUp = inNode->Up();
		PolyNode* newRoot = 0;


		if (theUp->IsRoot())	{
			inNode->Detach();
			if (theUp->down->next != theUp->down)	{
				newRoot = new PolyNode();
				newRoot->SetTree(this);
				theUp->AttachTo(newRoot);
				theUp->mProb = inNode->mProb;
			}
			else	{
				newRoot = theUp;
			}
		}

		else	{
			newRoot = theUp->FlipFlop();
			if ( ! newRoot)	{
				newRoot = new PolyNode();
				newRoot->SetTree(this);
			}
			inNode->Detach();
			theUp->AttachTo(newRoot);
			theUp->mProb = inNode->mProb;
		}
		inNode->AttachTo(newRoot);
		mRoot = newRoot;
	}

	double lengthafter = GetLength();
	if (fabs(lengthafter - lengthbefore) > 1e-8)	{
		cerr << "error in rerooting: length not conserved\n";
		cerr << "length before : " << lengthbefore << '\n';
		cerr << "length after  : " << lengthafter << '\n';
		cerr << lengthbefore - lengthafter << '\n';
		// exit(1);
	}

	double totallength = mRoot->down->branchLength + mRoot->down->next->branchLength;
	mRoot->down->branchLength  = totallength / 2;
	mRoot->down->next->branchLength  = totallength / 2;
	
}
void SHAPE_POLY_SET::importTree( PolyTree* tree)
{
    m_polys.clear();

    for( PolyNode* n = tree->GetFirst(); n; n = n->GetNext() )
    {
        if( !n->IsHole() )
        {
            POLYGON paths;
            paths.push_back( convertFromClipper( n->Contour ) );

            for( unsigned int i = 0; i < n->Childs.size(); i++ )
                paths.push_back( convertFromClipper( n->Childs[i]->Contour ) );

            m_polys.push_back(paths);
        }
    }
}
示例#4
0
int Tree::ReadPhylip(istream& is, PolyNode* currentNode)	{

// 	int verbose = 1;
	PolyNode* node = 0;
	double d;

	int END = 0;

	char c = is.peek();
	while ((c == ' ') || (c == '\n') || (c == '\t'))	{
		is.get();
		c = is.peek();
	}


	while( (! is.eof()) && (! END) )	{

		string s;
		char c = is.peek();

		// cerr << c ;

		switch (c)	{

			case '\n'  :
			case ' '   :
			case '\t'  :

				is >> c;

				if (verbose)	{
					cerr << c;
				}

				break;


			case '('   :

				is >> c;
				if (verbose)	{
					cerr << c;
				}

				// make a new polynode
				node = new PolyNode();
				node->AttachTo(currentNode);
				currentNode = node;

				break;


			case ','   :

				is >> c;
				if (verbose)	{
					cerr << c;
				}
				node = new PolyNode();
				if (currentNode->IsRoot())	{
					cerr << "error in reading tree file : found a coma not within brackets\n";
					exit(1);
				}
				node->AttachTo(currentNode->Up());
				currentNode = node;

				break;


			case ')' :

				is >> c;
				if (verbose)	{
					cerr << c;
				}
				if (currentNode->IsRoot())	{
					cerr << "error in reading tree file: found more closing than opening brackets\n";
					exit(1);
				}

				currentNode = currentNode->Up();

				// check whether is followed by a digit, a ':', a ')' or  a ',' (anything else will throw exception)
				c = is.peek();

				switch(c)	{

					case '0':
					case '1':
					case '2':
					case '3':
					case '4':
					case '5':
					case '6':
					case '7':
					case '8':
					case '9':

						// probability
						is >> d;
						if (verbose)	{
							cerr << d;
						}

						currentNode->SetProb(d);

						// then check whether is further followed by ':' or ',' or ')' (anything else exits)

						c = is.peek();

						switch(c)	{

							case ':' 	:

								is >> c;
								if (verbose)	{
									cerr << c;
								}

								// read branchLength
								// and check that it is followed either by ',' or by ')'

								is >> d;
								if (verbose)	{
									cerr << "BL" << d;
								}
								currentNode->SetBranchLength(d);

								c = is.peek();

								if ((c != ',') && (c != ')') && (c != ';'))	{
									cerr << "error\n";
									cerr << c << '\n';
									exit(1);
								}

							break;

							case ',' :
							case ')' :

							break;

							default	:

								cerr << "error in reading tree file : after reading a branchlength of an internal node\n";
								cerr << c << '\n';
								double d;
								is >> d;
								cerr << d << '\n';
								exit(1);

							break;
						}

					break;


					case ':' 	:

						is >> c;
						if (verbose)	{
							cerr << c;
						}

						// read branchLength
						// and check that it is followed either by ',' or by ')'
						is >> d;
						if (verbose)	{
							cerr << "BL" << d;
						}

						currentNode->SetBranchLength(d);

						c = is.peek();

						if ((c != ',') && (c != ')') && (c != ';'))	{
							cerr << "error\n";
							cerr << c << '\n';
							exit(1);
						}

					break;

					case ';' :
					case ',' :
					case ')' :
					break;

					default	:

						cerr << "error in reading tree file\n";
						cerr << "character : " << c << '\n';
						exit(1);

					break;

				}

			break;


			case ';'	:

				is >> c;
				if (verbose)	{
					cerr << "END" << c;
				}

				// close the tree
				// current node should be root
				if (! currentNode->IsRoot())	{
					cerr << "error in reading tree file : lacking closing brackets overall\n";
					exit(1);
				}

				END = 1;

			break;


			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':

				// species label

				s == "";
				do	{
					s += c;
					is >> c;
					if (is.eof())	{
						cerr << "error in reading treefile : unexpected end of file in string\n";
						exit(1);
					}
					c = is.peek();
				}	while ((c != ',') && (c != ':') && (c != ')'));
				if (IsInt(s))	{
					int i = Int(s);
					// is >> i;
					if (verbose)	{
						cerr << i;
					}
					node->SetLabel(i);
				}
				else	{
					node->SetName(s);
				}
				
				// check whether is followed by : or , or ) (anything else will throw exception)
				c = is.peek();

				switch(c)	{

					case ':' :

						is >> c;
						if (verbose)	{
							cerr << c;
						}

						// branchlength
						double d;
						is >> d;
						if (verbose)	{
							cerr << "BL" << d;
						}

						node->SetBranchLength(d);

						c = is.peek();

						if ((c != ',') && (c != ')'))	{
							cerr << "error\n";
							cerr << c << '\n';
							exit(1);
						}

					break;

					case ',' :
					case ')' :

					break;

					default	:

						cerr << "error in reading tree file\n";
						cerr << "character : " << c << '\n';
						exit(1);

					break;

				}

			break;

			default :

				// assume this is a species name

				s == "";
				do	{
					s += c;
					is >> c;
					if (is.eof())	{
						return 0;
					}
					c = is.peek();
				}	while ((c != ',') && (c != ':') && (c != ')'));

				currentNode->SetName(s);
				if (verbose)	{
					cerr << '\"' << s << '\"';
				}

				// check whether is followed by : or , (anything else will throw exception)
				c = is.peek();

				switch(c)	{

					case ':' :

						is >> c;
						if (verbose)	{
							cerr << c;
						}

						// branchlength
						double d;
						is >> d;
						if (verbose)	{
							cerr << "BL" << d;
						}

						node->SetBranchLength(d);
					break;



					case ',' :
					case ')':

					break;

					default	:

						cerr << "error in reading tree file : after reading species name\n";
						exit(1);

					break;

				}


			break;

		}
	}
	if (verbose)	{
		cerr << "tree read : ok " << '\n' << '\n';
		cerr.flush();
	}
	return 1;
}
示例#5
0
    void triangulate(const Polygon& inputPoly, std::vector<Mesh>& outputMeshes)
    {
        // Use Clipper to ensure strictly simple polygons
        using namespace ClipperLib;
        Clipper clipper;
        clipper.StrictlySimple(true);

        try
        {
            clipper.AddPaths(polyToClipperPaths(inputPoly), ptSubject, true);
        }
        catch (...)
        {
            std::cerr << "Error in Clipper::AddPaths" << std::endl;
            return;
        }

        PolyTree polyTree;
        clipper.Execute(ctUnion, polyTree, pftNonZero, pftNonZero);

        // Traverse the PolyTree nodes and triangulate them with only their children holes
        PolyNode *currentNode = polyTree.GetFirst();
        while(currentNode != NULL)
        {
            // The holes are only used as the children of the contours
            if (currentNode->IsHole())
            {
                currentNode = currentNode->GetNext();
                continue;
            }

            // Convert to poly2tri's format
            std::vector<p2t::Point> allPoints;
            std::vector<size_t> linesSizes;

            // Contour
            for (const auto& pt : currentNode->Contour)
                allPoints.emplace_back(static_cast<double>(pt.X), static_cast<double>(pt.Y));
            linesSizes.push_back(allPoints.size());

            // Holes
            for(const auto childNode : currentNode->Childs)
            {
                // Slightly modify the polygon to guarantee no duplicate points
                edgeShrink(childNode->Contour);

                for (const auto& pt : childNode->Contour)
                    allPoints.emplace_back(static_cast<double>(pt.X), static_cast<double>(pt.Y));
                linesSizes.push_back(allPoints.size());
            }

            // Poly2Tri uses pointers to points
            std::vector<p2t::Point*> contourLine;
            std::vector<std::vector<p2t::Point*>> holes;

            auto nbLines = linesSizes.size();
            size_t start = 0;
            for (size_t i = 0; i < nbLines; ++i)
            {
                size_t end = linesSizes[i];
                std::vector<p2t::Point*> line;
                line.reserve(end - start);
                for (size_t j = start; j < end; ++j)
                    line.push_back(&allPoints[j]);
                start = end;

                if (!i) contourLine = std::move(line);
                else	holes.push_back(std::move(line));
            }

            // Set the contour in poly2tri
            p2t::CDT cdt(contourLine);

            // Add the holes
            for(auto& hole : holes)
                cdt.AddHole(hole);

            // Do the actual triangulation
            cdt.Triangulate();

            // Downscale the points and add them to the mesh
            Mesh mesh;
            for (const auto pt : allPoints)
                mesh.addPoint(convert(pt));

            // Convert the triangles
            auto triangles = cdt.GetTriangles();
            auto firstPt = allPoints.data();
            for (const auto triangle : triangles)
            {
                int ptId1 = std::distance(firstPt, triangle->GetPoint(0));
                int ptId2 = std::distance(firstPt, triangle->GetPoint(1));
                int ptId3 = std::distance(firstPt, triangle->GetPoint(2));
                mesh.addTriangle(ptId1, ptId2, ptId3);
            }
            outputMeshes.push_back(mesh);

            currentNode = currentNode->GetNext();
        }
    }