//---------------------------------------------------------------------------- BspPolygon2* Boolean2D::ConstructPentagon () { const int numVertices = 5; double primitiveAngle = Mathd::TWO_PI/numVertices; double radius = 0.35*GetWidth(); double cx = 0.5*GetWidth(), cy = 0.5*GetWidth(); Vector2d vertices[numVertices]; for (int i = 0; i < numVertices; ++i) { double angle = i*primitiveAngle; vertices[i].X() = cx + radius*Mathd::Cos(angle); vertices[i].Y() = cy + radius*Mathd::Sin(angle); } BspPolygon2* poly = new0 BspPolygon2(); for (int i0 = numVertices - 1, i1 = 0; i1 < numVertices; i0 = i1++) { poly->InsertVertex(vertices[i1]); poly->InsertEdge(Edge2(i0, i1)); } poly->Finalize(); return poly; }
//---------------------------------------------------------------------------- BspPolygon2* Boolean2D::ConstructInvertedEll () { double w = (double)GetWidth(); double d1d8 = 0.125*w; double d2d8 = 0.250*w; double d3d8 = 0.375*w; double d5d8 = 0.625*w; double d6d8 = 0.750*w; double d7d8 = 0.875*w; const int numVertices = 10; Vector2d vertices[numVertices] = { Vector2d(d1d8, d1d8), Vector2d(d3d8, d1d8), Vector2d(d3d8, d3d8), Vector2d(d2d8, d3d8), Vector2d(d2d8, d6d8), Vector2d(d5d8, d6d8), Vector2d(d5d8, d5d8), Vector2d(d7d8, d5d8), Vector2d(d7d8, d7d8), Vector2d(d1d8, d7d8) }; BspPolygon2* poly = new0 BspPolygon2(); for (int i0 = numVertices - 1, i1 = 0; i1 < numVertices; i0 = i1++) { poly->InsertVertex(vertices[i1]); poly->InsertEdge(Edge2(i0, i1)); } poly->Finalize(); return poly; }
//---------------------------------------------------------------------------- void BspTree2::GetNegPartition (const BspPolygon2& polygon, const Vector2d& v0, const Vector2d& v1, BspPolygon2& pos, BspPolygon2& neg, BspPolygon2& coSame, BspPolygon2& coDiff) const { if (mNegChild) { mNegChild->GetPartition(polygon, v0, v1, pos, neg, coSame, coDiff); } else { int i0 = neg.InsertVertex(v0); int i1 = neg.InsertVertex(v1); neg.InsertEdge(Edge2(i0, i1)); } }
vector <Edge2> CueTable::generatePocketEdges( const Circle& circle, const Edge2& startEdge, const Edge2& endEdge, int quality ){ vector <Edge2> pocketEdges; float startAngle = orientedAngle(-startEdge.getDirection(),vec2(0,1)); float endAngle = orientedAngle(endEdge.getDirection(), vec2(0,1)); float startRad = radians( startAngle ); float endRad = radians( endAngle ); float alpha = (endAngle - startAngle) / (float)(quality - 1); float alphaRad = radians( alpha ); float tangetialFactor = tan( alphaRad ); float radialFactor = cos( alphaRad ); float x = circle.radius * cos( 0.0f ); float y = circle.radius * sin( 0.0f ); auto rotate = [=]( float x, float y) -> vec2 { vec3 i = vec3( x, 0, y ); vec3 r = angleAxis(startAngle + 90, vec3(0,1,0) ) * i; return vec2( r.x, r.z ); }; for (int i = 0; i < quality - 1; i++){ vec2 v0 = circle.center + rotate( x,y ); float tx = -y; float ty = x; x += tx * tangetialFactor; y += ty * tangetialFactor; x *= radialFactor; y *= radialFactor; vec2 v1 = circle.center + rotate( x,y ); pocketEdges.push_back( Edge2(v0, v1) ); } return pocketEdges; }
//---------------------------------------------------------------------------- BspPolygon2* Boolean2D::ConstructSShape () { double w = (double)GetWidth(); double d10d32 = 10.0*w/32.0; double d12d32 = 12.0*w/32.0; double d13d32 = 13.0*w/32.0; double d16d32 = 16.0*w/32.0; double d19d32 = 19.0*w/32.0; double d20d32 = 20.0*w/32.0; double d22d32 = 22.0*w/32.0; double d24d32 = 24.0*w/32.0; double d26d32 = 26.0*w/32.0; double d28d32 = 28.0*w/32.0; const int numVertices = 12; Vector2d vertices[numVertices] = { Vector2d(d24d32, d10d32), Vector2d(d28d32, d10d32), Vector2d(d28d32, d16d32), Vector2d(d22d32, d16d32), Vector2d(d22d32, d19d32), Vector2d(d24d32, d19d32), Vector2d(d24d32, d22d32), Vector2d(d20d32, d22d32), Vector2d(d20d32, d13d32), Vector2d(d26d32, d13d32), Vector2d(d26d32, d12d32), Vector2d(d24d32, d12d32) }; BspPolygon2* poly = new0 BspPolygon2(); for (int i0 = numVertices - 1, i1 = 0; i1 < numVertices; i0 = i1++) { poly->InsertVertex(vertices[i1]); poly->InsertEdge(Edge2(i0, i1)); } poly->Finalize(); return poly; }
//---------------------------------------------------------------------------- BspPolygon2* Boolean2D::ConstructSquare () { double w = (double)GetWidth(); double d2d8 = 0.250*w; double d6d8 = 0.750*w; const int numVertices = 4; Vector2d vertices[numVertices] = { Vector2d(d2d8, d2d8), Vector2d(d6d8, d2d8), Vector2d(d6d8, d6d8), Vector2d(d2d8, d6d8) }; BspPolygon2* poly = new0 BspPolygon2(); for (int i0 = numVertices - 1, i1 = 0; i1 < numVertices; i0 = i1++) { poly->InsertVertex(vertices[i1]); poly->InsertEdge(Edge2(i0, i1)); } poly->Finalize(); return poly; }
//---------------------------------------------------------------------------- BspPolygon2* Boolean2D::ConstructPolyWithHoles () { double w = (double)GetWidth(); double d2d16 = 2.0*w/16.0; double d3d16 = 3.0*w/16.0; double d4d16 = 4.0*w/16.0; double d6d16 = 6.0*w/16.0; double d14d16 = 14.0*w/16.0; const int numVertices = 6; Vector2d vertices[numVertices] = { // outer boundary Vector2d(d2d16, d2d16), Vector2d(d14d16, d2d16), Vector2d(d2d16, d14d16), // inner boundary Vector2d(d4d16, d3d16), Vector2d(d6d16, d6d16), Vector2d(d6d16, d3d16) }; BspPolygon2* poly = new0 BspPolygon2(); for (int i = 0; i < numVertices; ++i) { poly->InsertVertex(vertices[i]); } poly->InsertEdge(Edge2(0, 1)); poly->InsertEdge(Edge2(1, 2)); poly->InsertEdge(Edge2(2, 0)); poly->InsertEdge(Edge2(3, 4)); poly->InsertEdge(Edge2(4, 5)); poly->InsertEdge(Edge2(5, 3)); poly->Finalize(); return poly; }
//---------------------------------------------------------------------------- BspTree2::BspTree2 (BspPolygon2& polygon, const EArray& edges) { assertion(edges.size() > 0, "Invalid input.\n"); // Construct splitting line from first edge. Vector2d end0 = polygon.mVArray[edges[0].I0]; Vector2d end1 = polygon.mVArray[edges[0].I1]; // Add edge to coincident list. mCoincident.push_back(edges[0]); // Split remaining edges. EArray posArray, negArray; int imax = (int)edges.size(); for (int i = 1; i < imax; ++i) { int v0 = edges[i].I0; int v1 = edges[i].I1; Vector2d vertex0 = polygon.mVArray[v0]; Vector2d vertex1 = polygon.mVArray[v1]; Vector2d intr; int vmid; switch (Classify(end0, end1, vertex0, vertex1, intr)) { case TRANSVERSE_POSITIVE: // modify edge <V0,V1> to <V0,I> and add new edge <I,V1> vmid = polygon.InsertVertex(intr); polygon.SplitEdge(v0, v1, vmid); posArray.push_back(Edge2(vmid, v1)); negArray.push_back(Edge2(v0, vmid)); break; case TRANSVERSE_NEGATIVE: // modify edge <V0,V1> to <V0,I> and add new edge <I,V1> vmid = polygon.InsertVertex(intr); polygon.SplitEdge(v0, v1, vmid); posArray.push_back(Edge2(v0, vmid)); negArray.push_back(Edge2(vmid, v1)); break; case ALL_POSITIVE: posArray.push_back(edges[i]); break; case ALL_NEGATIVE: negArray.push_back(edges[i]); break; default: // COINCIDENT mCoincident.push_back(edges[i]); break; } } if (posArray.size() > 0) { mPosChild = new0 BspTree2(polygon, posArray); } else { mPosChild = 0; } if (negArray.size() > 0) { mNegChild = new0 BspTree2(polygon, negArray); } else { mNegChild = 0; } }
bool CueTable::insertPocket(Polygon2& shape, vec2 holePos){ const Circle circle(holePos, 1.0f); auto edges = &shape.getEdges(); int countEdges = 0; for(uint i = 0; i < edges->size(); i++){ Edge2 edge = edges->at(i); if(circle.inside(edge[0]) ^ circle.inside(edge[1])){ countEdges++; } } if(countEdges > 2){ return false; }else if (countEdges == 1){ return false; } for( auto it = edges->begin(); it != edges->end(); ){ Edge2 edge = (*it); if(circle.inside(edge[0]) && circle.inside(edge[1])){ it = edges->erase( it ); }else{ it++; } } for( auto it = edges->begin(); it != edges->end(); ){ Edge2 edge = (*it); vec2 alpha; IntersectionType intType = circleIntersection(edge, circle, alpha.x, alpha.y); vec2 edge0 = edge[0]; vec2 edge1 = edge[1]; vec2 hit0 = lerp(edge0,edge1,alpha[0]); vec2 hit1 = lerp(edge0,edge1,alpha[1]); switch (intType) { case IMPALE: { it = edges->erase( it ); it = edges->insert(it, Edge2(edge0, hit0)); /*vector<Edge2> pocketEdges = generatePocketEdges(circle, Edge2(edge0, hit0), Edge2(hit1, edge1), 10); for( auto& e : pocketEdges ) it = edges->insert( it + 1, e );*/ it = edges->insert(it + 1, Edge2(hit1, edge1)); it--; break; } case POKE: { it->at(1) = hit0; /*vector<Edge2> pocketEdges = generatePocketEdges(circle, *it, *(it+1), 10); for( auto& e : pocketEdges ) it = edges->insert( it + 1, e );*/ break; } case EXITWOUND: { it->at(0) = hit1; break; } case COMPLETELYINSIDE: case FALLSHORT: case PAST: case NONE: break; case INVALID: default: assert(0); } it++; } return true; }