МД (1194692), страница 20
Текст из файла (страница 20)
Ортоцентр - точкаbool GetCoordsCentrTreugolnika(point p1, point p2, point p3, point2D &p4){float S=((p1.X-p3.X)*(p2.Y-p3.Y)-(p2.X-p3.X)*(p1.Y-p3.Y))*0.5; ///Поиск площади треугольникаif (S==0) return false; ///В случае, когда треугольник складывается в линию, функция предупреждает об этом и заканчивает свою работуfloat D=2*(p1.X*(p2.Y-p3.Y)+p2.X*(p3.Y-p1.Y)+p3.X*(p1.Y-p2.Y));137p4.x=((p1.X*p1.X+p1.Y*p1.Y)*(p2.Y-p3.Y)+(p2.X*p2.X+p2.Y*p2.Y)*(p3.Yp1.Y)+(p3.X*p3.X+p3.Y*p3.Y)*(p1.Y-p2.Y))/D;p4.y=((p1.X*p1.X+p1.Y*p1.Y)*(p3.X-p2.X)+(p2.X*p2.X+p2.Y*p2.Y)*(p1.Xp3.X)+(p3.X*p3.X+p3.Y*p3.Y)*(p2.X-p1.X))/D;return true;}///Перегрузка функции сравнения точекbool HelpFunctionForSort(point2D a, point2D b){if (atanTrueDegree(TempBasePoint.x-a.x,TempBasePoint.ya.y)>atanTrueDegree(TempBasePoint.x-b.x,TempBasePoint.y-b.y)){return false;}return true;}///Создание выпуклого многоугольника по ID, точки для генерации сетки Вороного (требовательна к оперативной памяти)void CreatePligoneForPoint(int currentID){MeabyPoint.clear();point2D tmp;///Цикл заполнения массива кандидатов точек, представляющих собой многоугольник (безфильтрации)for (int i=0;i<InnerPoints.size();i++){for (int j=i+1;j<InnerPoints.size();j++){if (i==currentID || j==currentID) continue;if (!GetCoordsCentrTreugolnika(InnerPoints[currentID], InnerPoints[i], InnerPoints[j], tmp)) continue;MeabyPoint.push_back(tmp);}}cout<<"Create "<<MeabyPoint.size()<<" subPoints"<<endl;///Фильтрация промежуточных точек - удаление всех точек, что не относится к многоугольнику.
Усекает все точки стоящие за выпуклым многоугольникомfor (int i=0;i<MeabyPoint.size();i++){for (int j=0;j<InnerPoints.size();j++){if (j==currentID) continue;float p1x=InnerPoints[currentID].X;float p1y=InnerPoints[currentID].Y;float p2x=InnerPoints[j].X;float p2y=InnerPoints[j].Y;float np1x, np1y, np2x, np2y;GetPerpendicular(p1x,p1y,p2x,p2y,np1x,np1y,np2x,np2y);///Удаление точки, стоящей за выпуклым многоугольникомif (IntersectLine2Otrezok(np1x,np1y,np2x,np2y,p1x,p1y,MeabyPoint[i].x,MeabyPoint[i].y)){MeabyPoint.erase(MeabyPoint.begin()+i,MeabyPoint.begin()+i+1);i=0;j=0;break;}}}cout<<"After clearing "<<MeabyPoint.size()<<" subPoints"<<endl;TempBasePoint.x=InnerPoints[currentID].X;TempBasePoint.y=InnerPoints[currentID].Y;///Сортировка точек после отчисткиsort(MeabyPoint.begin(), MeabyPoint.end(),HelpFunctionForSort);///Заполнение массива многоугольников сетки ВороногоPoligoneBase.clear();poligone tmpPoly;for (int i=0;i<MeabyPoint.size();i++){tmp.x=MeabyPoint[i].x;tmp.y=MeabyPoint[i].y;tmpPoly.StackCorners.push_back(tmp);}PoligoneBase.push_back(tmpPoly);}///Функция, проверяющая нахождение точки внутри замкнутого контураbool FindPointIntoLoop(float inX,float inY){float dAlpha=0; ///Временный угол, к которому суммируется дельта от переходов по точкамint countIDInLoops=0;///Количество найденных контуров///Цикл обхода по всем точкам контура с суммированием во временный уголfor (int i=0;i<OutLineSeparation.size()-1;i++){if (OutLineSeparationID[i]!=OutLineSeparationID[i+1]){138if (fabs(dAlpha)>0.001 ) countIDInLoops++;dAlpha=0;continue;}float p1x=OutLineSeparation[i].X-inX;float p1y=OutLineSeparation[i].Y-inY;float p2x=OutLineSeparation[i+1].X-inX;float p2y=OutLineSeparation[i+1].Y-inY;float angle=atanTrueDegree(p1x,p1y)-atanTrueDegree(p2x,p2y);if (angle>180) angle=-(360-atanTrueDegree(p1x,p1y)+atanTrueDegree(p2x,p2y));if (angle<-180) angle=(360-atanTrueDegree(p2x,p2y)+atanTrueDegree(p1x,p1y));dAlpha+=angle;}if (fabs(dAlpha)>0.001 ) countIDInLoops++;if (countIDInLoops%2==1) return true;else return false;}///Функция установки множества беспорядочных точек внутри замкнутого контураvoid SetInnerPointsRand(){InnerPoints.clear();point tmp;if (OutLineSeparation.size()<2) return;while (InnerPoints.size()<maxInnerRandPoint){tmp.X=(((float)rand()/(float)(RAND_MAX)) * fabs(GabariteMaxXGabariteMinX))+GabariteMinX;tmp.Y=(((float)rand()/(float)(RAND_MAX)) * fabs(GabariteMaxYGabariteMinY))+GabariteMinY;tmp.Z=SlicerHeight;if (FindPointIntoLoop(tmp.X,tmp.Y)) InnerPoints.push_back(tmp);}}///Функция установки множества точек в виде систематизированной сетки внутри замкнутого контураvoid SetInnerPointsGrid(){InnerPoints.clear();point tmp;for (float dx=GabariteMinX+GridSize/2;dx<GabariteMaxX;dx+=GridSize){for (float dy=GabariteMinY+GridSize/2;dy<GabariteMaxY;dy+=GridSize){tmp.X=dx;tmp.Y=dy;tmp.Z=SlicerHeight;if (FindPointIntoLoop(dx,dy)) InnerPoints.push_back(tmp);}}}///Функция генерации одного замкнутого контураvoid FindSeparateLayerOutLine(){/// Подготовка к работе, очистка, создание базовой точки т т.д.OutLineSeparation.clear();OutLineSeparationID.clear();point tempPoint;int tempID;int thisIDLine;tempPoint.X=pointSeparation[0].X;tempPoint.Y=pointSeparation[0].Y;tempPoint.Z=pointSeparation[0].Z;tempID=0;thisIDLine=0;OutLineSeparation.push_back(tempPoint);OutLineSeparationID.push_back(thisIDLine);///Бесконечный цикл прохода по всем точкам пересечения плоскости с модельюwhile (pointSeparationID.size()>0){for(int i=0;i<pointSeparation.size();i++){if (fabs(pointSeparation[i].X-tempPoint.X)<0.001 &&fabs(pointSeparation[i].Y-tempPoint.Y)<0.001 &&fabs(pointSeparation[i].Z-tempPoint.Z)<0.001){for (int j=0;j<pointSeparation.size();j++){if ((pointSeparation[j].X!=pointSeparation[i].X ||pointSeparation[j].Y!=pointSeparation[i].Y ||pointSeparation[j].Z!=pointSeparation[i].Z) &&pointSeparationID[j]==pointSeparationID[i]){139tempPoint.X=pointSeparation[j].X;tempPoint.Y=pointSeparation[j].Y;tempPoint.Z=pointSeparation[j].Z;OutLineSeparation.push_back(tempPoint);OutLineSeparationID.push_back(thisIDLine);tempID=pointSeparationID[i];///Фильтрация получившегося констра на совпадение IDfor(int k=0;k<pointSeparationID.size();k++){if (pointSeparationID[k]==tempID){pointSeparation.erase(pointSeparation.begin()+k,pointSeparation.begin()+k+1);pointSeparationID.erase(pointSeparationID.begin()+k,pointSeparationID.begin()+k+1);break;}}for(int k=0;k<pointSeparationID.size();k++){if (pointSeparationID[k]==tempID){pointSeparation.erase(pointSeparation.begin()+k,pointSeparation.begin()+k+1);pointSeparationID.erase(pointSeparationID.begin()+k,pointSeparationID.begin()+k+1);break;}}break;}}break;}///Поиск количества контуровif (i==pointSeparation.size()-1){tempPoint.X=pointSeparation[0].X;tempPoint.Y=pointSeparation[0].Y;tempPoint.Z=pointSeparation[0].Z;tempID=0;OutLineSeparation.push_back(tempPoint);OutLineSeparationID.push_back(thisIDLine+1);thisIDLine++; }}}///Дополнительная фильтрация массива контуров, для удаления лишних вершин, в узле которойлиния не изгибаетсяint thisPointStartLine=0;while (thisPointStartLine<OutLineSeparation.size()-2) {if (OutLineSeparationID[thisPointStartLine]!=OutLineSeparationID[thisPointStartLine+2]) {thisPointStartLine+=2;}float dx1=fabs(OutLineSeparation[thisPointStartLine].XOutLineSeparation[thisPointStartLine+1].X);float dy1=fabs(OutLineSeparation[thisPointStartLine].YOutLineSeparation[thisPointStartLine+1].Y);float dx2=fabs(OutLineSeparation[thisPointStartLine+1].XOutLineSeparation[thisPointStartLine+2].X);float dy2=fabs(OutLineSeparation[thisPointStartLine+1].YOutLineSeparation[thisPointStartLine+2].Y);if ((dx1/dy1)==(dx2/dy2)){OutLineSeparation[thisPointStartLine+1].X=OutLineSeparation[thisPointStartLine+2].X;OutLineSeparation[thisPointStartLine+1].Y=OutLineSeparation[thisPointStartLine+2].Y;OutLineSeparation[thisPointStartLine+1].Z=OutLineSeparation[thisPointStartLine+2].Z;OutLineSeparation.erase(OutLineSeparation.begin()+thisPointStartLine+2,OutLineSeparation.begin()+thisPointStartLine+3);OutLineSeparatitionID.erase(OutLineSeparationID.begin()+thisPointStartLine+2,OutLineSeparationID.begin()+thisPointStartLine+3);thisPointStartLine=0;}else thisPointStartLine+=1;}offsetUpForLinePerimetr=OutLineSeparation.size();140countLoops=thisIDLine+1;///Одна из основных функций (запускается перед предыдущей).
Выполняет генерацию точек пересечения плоскости сечения с треугольниками, из которой состоит модельvoid FindSeparatePoint(){int vert2;pointSeparation.clear();pointSeparationID.clear();///Основной цикл прохода по всем треугольниками моделиfor(int trianN=0;trianN<triangleBase.size();trianN++){///Преобразование с определением, к какой грани относится та или иная точка на треугольникеfor (int vert1=0;vert1<3;vert1++){if (vert1==0) vert2=1;if (vert1==1) vert2=2;if (vert1==2) vert2=0;///Проверка факта параллельности треугольника секущей плоскостиif (triangleBase[trianN].p[vert1].Z==SlicerHeight) {cout<<"Danger triangle pararell slisser plane "<<trianN<<endl;pointSeparation.clear();pointSeparationID.clear();return;}///Определениефакта, что плоскость пересекает треугольник (пересечение по 2 граням, не может быть пересечения по 1 или 3)if ((triangleBase[trianN].p[vert1].Z<SlicerHeight && triangleBase[trianN].p[vert2].Z>SlicerHeight)||(triangleBase[trianN].p[vert1].Z>SlicerHeight && triangleBase[trianN].p[vert2].Z<SlicerHeight)){float difX=triangleBase[trianN].p[vert2].XtriangleBase[trianN].p[vert1].X;float difY=triangleBase[trianN].p[vert2].YtriangleBase[trianN].p[vert1].Y;float difZ=triangleBase[trianN].p[vert2].ZtriangleBase[trianN].p[vert1].Z;float t=(SlicerHeight-triangleBase[trianN].p[vert1].Z)/(difZ);if (pointSeparationID.size()>0){if (pointSeparationID[pointSeparationID.size()-1]==trianN &&(fabs(pointSeparation[pointSeparation.size()-1].X(triangleBase[trianN].p[vert1].X+difX*t)))<0.001 &&(fabs(pointSeparation[pointSeparation.size()-1].Y(triangleBase[trianN].p[vert1].Y+difY*t)))<0.001){pointSeparation.pop_back();pointSeparationID.pop_back();continue;}}point temp;temp.X=triangleBase[trianN].p[vert1].X+difX*t;temp.Y=triangleBase[trianN].p[vert1].Y+difY*t;temp.Z=triangleBase[trianN].p[vert1].Z+difZ*t;pointSeparation.push_back(temp);pointSeparationID.push_back(trianN);}}}///Функция поиска габаритных размеров моделиvoid FindGabarite(){float minX=triangleBase[0].p[0].X;float maxX=triangleBase[0].p[0].X;float minY=triangleBase[0].p[0].Y;float maxY=triangleBase[0].p[0].Y;float minZ=triangleBase[0].p[0].Z;float maxZ=triangleBase[0].p[0].Z;for(int i=0;i<triangleBase.size();i++){for (int j=0;j<3;j++){if (triangleBase[i].p[j].X>maxX) maxX=triangleBase[i].p[j].X;if (triangleBase[i].p[j].Y>maxY) maxY=triangleBase[i].p[j].Y;if (triangleBase[i].p[j].Z>maxZ) maxZ=triangleBase[i].p[j].Z;if (triangleBase[i].p[j].X<minX) minX=triangleBase[i].p[j].X;141if (triangleBase[i].p[j].Y<minY) minY=triangleBase[i].p[j].Y;if (triangleBase[i].p[j].Z<minZ) minZ=triangleBase[i].p[j].Z;}}GabariteMaxX=maxX;GabariteMinX=minX;GabariteMaxY=maxY;GabariteMinY=minY;GabariteMaxZ=maxZ;GabariteMinZ=minZ;}///Подстройка объекта таким образом, чтобы его нижняя грань касалась стола печатиvoid PlateBaseBody(){float offsetZ=0;FindGabarite();if (GabariteMinZ<0) offsetZ=-GabariteMinZ;if (GabariteMinZ>0) offsetZ=GabariteMinZ;for (int i=0;i<triangleBase.size();i++){for (int j=0;j<3;j++){triangleBase[i].p[j].Z=triangleBase[i].p[j].Z+offsetZ;}}FindGabarite();}///Функция поворота всей модели вокруг своего центраvoid RotateBody(int axis){FindGabarite();float NewNormalX, NewNormalY, NewNormalZ;float NewPointX, NewPointY, NewPointZ;float PointMidleX, PointMidleY, PointMidleZ;///Определение центра моделиPointMidleX=((GabariteMaxX-GabariteMinX)/2)+GabariteMinX;PointMidleY=((GabariteMaxY-GabariteMinY)/2)+GabariteMinY;PointMidleZ=((GabariteMaxZ-GabariteMinZ)/2)+GabariteMinZ;///Цикл сдвижки кадой точки через матрицу поворота в 3D пространствеfor (int i=0;i<triangleBase.size();i++){if (axis==0){NewNormalX=triangleBase[i].Normal.X;NewNormalY=triangleBase[i].Normal.Y*cos(M_PI/4)+triangleBase[i].Normal.Z*sin(M_PI/4);NewNormalZ=triangleBase[i].Normal.Y*sin(M_PI/4)+triangleBase[i].Normal.Z*cos(M_PI/4);}if (axis==1){NewNormalX=triangleBase[i].Normal.X*cos(M_PI/4)+triangleBase[i].Normal.Z*sin(M_PI/4);NewNormalY=triangleBase[i].Normal.Y;NewNormalZ=triangleBase[i].Normal.X*sin(M_PI/4)+triangleBase[i].Normal.Z*cos(M_PI/4);}if (axis==2){NewNormalX=triangleBase[i].Normal.X*cos(M_PI/4)triangleBase[i].Normal.Y*sin(M_PI/4);NewNormalY=triangleBase[i].Normal.X*sin(M_PI/4)+triangleBase[i].Normal.Y*cos(M_PI/4);NewNormalZ=triangleBase[i].Normal.Z;}///Дополнительное смещение нормалей модели для верного вычисления освещения моделиtriangleBase[i].Normal.X=NewNormalX;triangleBase[i].Normal.Y=NewNormalY;triangleBase[i].Normal.Z=NewNormalZ;for (int j=0;j<3;j++){if (axis==0){NewPointX=triangleBase[i].p[j].X;NewPointY=((triangleBase[i].p[j].YPointMidleY)*cos(M_PI/4)+(triangleBase[i].p[j].Z-PointMidleZ)*sin(M_PI/4));NewPointZ=(-1*(triangleBase[i].p[j].YPointMidleY)*sin(M_PI/4)+(triangleBase[i].p[j].Z-PointMidleZ)*cos(M_PI/4));}if (axis==1){NewPointX=((triangleBase[i].p[j].XPointMidleX)*cos(M_PI/4)+(triangleBase[i].p[j].Z-PointMidleZ)*sin(M_PI/4));NewPointY=triangleBase[i].p[j].Y;142NewPointZ=(-1*(triangleBase[i].p[j].XPointMidleY)*sin(M_PI/4)+(triangleBase[i].p[j].Z-PointMidleZ)*cos(M_PI/4));}if (axis==2){NewPointX=((triangleBase[i].p[j].X-PointMidleX)*cos(M_PI/4)(triangleBase[i].p[j].Y-PointMidleY)*sin(M_PI/4));NewPointY=((triangleBase[i].p[j].XPointMidleY)*sin(M_PI/4)+(triangleBase[i].p[j].Y-PointMidleY)*cos(M_PI/4));NewPointZ=triangleBase[i].p[j].Z;}triangleBase[i].p[j].X=NewPointX;triangleBase[i].p[j].Y=NewPointY;triangleBase[i].p[j].Z=NewPointZ;}}FindGabarite(); }///Функция чтения файла STL и преобразование его в формат программы (суть - синтаксическийразбор файла)bool ReadSTLFile(string a){triangleBase.clear();string s;ifstream myfile (a.c_str());if (myfile.is_open()){int State=0;int Type=0;int countCoords=0;float points[3];triangle form;///В случае верного открытия файла производится полное чтение всех строк кода, касающиеся одной SOLID структурыwhile ( myfile.good() ){getline (myfile,s,' ');if (s!=""){if (State==1) {countCoords--;points[countCoords]=atof(s.c_str());///Из файла последовательно выбираются координаты точек треугольника икоординаты нормалейif (countCoords==0) {if (Type==1) {form.Normal.X=points[2];form.Normal.Y=points[1];form.Normal.Z=points[0];triangleBase.push_back(form);}if (Type>1) {triangleBase[triangleBase.size()-1].p[Type-2].X=points[2];triangleBase[triangleBase.size()-1].p[Type-2].Y=points[1];triangleBase[triangleBase.size()-1].p[Type-2].Z=points[0]; }State=0;}}///Функция состояний для синтаксического разбора файлаif (State==0) {if (s=="normal"){State=1;countCoords=3;Type=1;}if (s=="vertex"){State=1;countCoords=3;Type=Type+1;}} }}myfile.close();}FindGabarite();///После чтения выводится количество прочитанных треугольников в моделиcout<<"Triangle in file = "<<triangleBase.size()<<endl;if (triangleBase.size()>0) return true;return false;}///Системная функция, отвечающая за изменение размера отображающего окна143static void resize(int width, int height){const float ar = (float) width / (float) height;glViewport(0, 0, width, height);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(45, ar, 1.0f, 10.0f);glMatrixMode(GL_MODELVIEW);///Основная функция вывода на экран в изображения с использованием библиотеки GLUT.hstatic void display(void){const double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;const double a = t*90.0;///Подготовка сценыglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glLoadIdentity();//gluLookAt(0, 0, 6,0, 0, 0,0, 0, 1);glTranslatef(0,0,-5);glPushMatrix();///Поворот сценыglRotatef(angleCamRotateY+DeltaAngleCamRotateY,1,0,0);glRotatef(angleCamRotateX+DeltaAngleCamRotateX,0,1,0);glScalef(zoomScene,zoomScene,zoomScene);///Отображение осей координатglLineWidth(4);glBegin(GL_LINES);glNormal3f(0,0,1);glColor4f(1,0,0,1);glVertex3f(-0.3,0,0);glVertex3f(1,0,0);glColor4f(0,1,0,1);glVertex3f(0,-0.3,0);glVertex3f(0,1,0);glColor4f(0,0,1,1);glVertex3f(0,0,-0.3);glVertex3f(0,0,1);glEnd();///Отображение полигонов в виде замкнутых многоугольниковglLineWidth(1);glBegin(GL_LINES);glColor4f(1,1,1,0.5);glNormal3f(0.5,0.5,0.5);for (int i=0;i<PoligoneBase.size();i++){for (int j=0;j<PoligoneBase[i].StackCorners.size()-1;j++){glVertex3f(PoligoneBase[i].StackCorners[j].x,PoligoneBase[i].StackCorners[j].y,SlicerHeight);glVertex3f(PoligoneBase[i].StackCorners[j+1].x,PoligoneBase[i].StackCorners[j+1].y,SlicerHeight);}glVertex3f(PoligoneBase[i].StackCorners[PoligoneBase[i].StackCorners.size()1].x,PoligoneBase[i].StackCorners[PoligoneBase[i].StackCorners.size()-1].y,SlicerHeight);glVertex3f(PoligoneBase[i].StackCorners[0].x,PoligoneBase[i].StackCorners[0].y,SlicerHeight);}glEnd();///Отобрание замкнутого внешнего контура модели после слайсинга (в виде линии красногоцвета)glLineWidth(3);glBegin(GL_LINES);glColor4f(1,0,0,1);glNormal3f(0,0,1);for (int i=0;i<offsetUpForLinePerimetr-1;i++){if (OutLineSeparationID[i+1]==OutLineSeparationID[i]){glVertex3f(OutLineSeparation[i].X,OutLineSeparation[i].Y,OutLineSeparation[i].Z);144glVertex3f(OutLineSeparation[i+1].X,OutLineSeparation[i+1].Y,OutLineSeparation[i+1].Z);}}glEnd();///Отображение множества слоев после слайсинга модели (в виде линий зеленого цвета)glLineWidth(2);for (int j=0;j<OutLineLoop.size();j++){glBegin(GL_LINES);glColor4f(0,1,0,1);glNormal3f(0,0,1);for (int i=0;i<OutLineLoop.at(j).size()-1;i++){if (OutLineLoopID.at(j).at(i+1)==OutLineLoopID.at(j).at(i)){glVertex3f(OutLineLoop.at(j).at(i).X,OutLineLoop.at(j).at(i).Y,OutLineLoop.at(j).at(i).Z);glVertex3f(OutLineLoop.at(j).at(i+1).X,OutLineLoop.at(j).at(i+1).Y,OutLineLoop.at(j).at(i+1).Z);}}glEnd();}///Отображение точек в процессе подготовки к заливке сеткой ВороногоglPointSize(4);glBegin(GL_POINTS);glColor4f(0,0,1,1);for (int i=0;i<InnerPoints.size();i++){glVertex3f(InnerPoints[i].X,InnerPoints[i].Y,InnerPoints[i].Z);}glEnd();///Переопределение первой точки вывода заливкиglPointSize(8);glBegin(GL_POINTS);glColor4f(0,0,1,1);if (InnerPoints.size()>0) glVertex3f(InnerPoints[0].X,InnerPoints[0].Y,InnerPoints[0].Z);glEnd();///Отображение точек после процесса подготовки к разбиению Вороного (на данный момент неработает из-за зависимости от размера оперативной памяти)glPointSize(6);glBegin(GL_POINTS);glColor4f(1,1,1,1);for (int i=0;i<MeabyPoint.size();i++){glVertex3f(MeabyPoint[i].x,MeabyPoint[i].y,SlicerHeight);}glEnd();///Отработка момента скрытия модели и отображения моделиif (HideSolid) {glBegin(GL_TRIANGLES);glColor4f(0.8,0.8,0.1,0.8);for (int i=0;i<triangleBase.size();i++){glNormal3f(triangleBase[i].Normal.X,triangleBase[i].Normal.Y,triangleBase[i].Normal.Z);glVertex3f(triangleBase[i].p[0].X,triangleBase[i].p[0].Y,triangleBase[i].p[0].Z);glVertex3f(triangleBase[i].p[1].X,triangleBase[i].p[1].Y,triangleBase[i].p[1].Z);glVertex3f(triangleBase[i].p[2].X,triangleBase[i].p[2].Y,triangleBase[i].p[2].Z);}glEnd();}///Отображение плоскости слайсингаglColor4f(0.1,0.1,0.5,0.3);glBegin(GL_POLYGON);glNormal3f(0,0,1);glVertex3f(GabariteMinX-1,GabariteMinY-1,SlicerHeight);glVertex3f(GabariteMaxX+1,GabariteMinY-1,SlicerHeight);glVertex3f(GabariteMaxX+1,GabariteMaxY+1,SlicerHeight);glVertex3f(GabariteMinX-1,GabariteMaxY+1,SlicerHeight);glEnd();///Отображение точек пересечения модели и плоскости слайсинга145glPointSize(4);glBegin(GL_POINTS);glColor4f(1,0,0,1);for (int i=0;i<pointSeparation.size();i++){glVertex3f(pointSeparation[i].X,pointSeparation[i].Y,pointSeparation[i].Z);}glEnd();glPopMatrix();glutSwapBuffers();}///Функция, определяющая расстояние от точки до прямой по наименьшему пути - перпендикуляруfloat OffsetByLine(point P1, point P2, point O){float h=((P2.X-P1.X)*(O.Y-P1.Y)-(P2.Y-P1.Y)*(O.X-P1.X))/(float)sqrt((float)pow((P2.XP1.X)+(P2.Y-P1.Y),2));return h<0?-h:h;}///Функция, генерирующая множество контуров - полный слайсиг моделиstatic void GenerateLoopCycle(void){///Подготовка к слайсингу и определение параметров слайсингаif (OutLineSeparation.size()>0){cout<<"Count vertex = "<<OutLineSeparation.size()<<endl;}///Отчистка слоев и запоминание текущей высоты слайсингаfloat tempSliceHight = SlicerHeight;vector <point> tempLoop;vector <int> tempLoopID;OutLineLoop.clear();OutLineLoopID.clear();///Цикл слайсинга с использованием базовой функции слайсинга одного слояfor (float height=LayerHeight/2;height<GabariteMaxZ;height+=LayerHeight){SlicerHeight=height;FindSeparatePoint();FindSeparateLayerOutLine();tempLoop=OutLineSeparation;tempLoopID=OutLineSeparationID;OutLineLoop.push_back(tempLoop);OutLineLoopID.push_back(tempLoopID);}OutLineSeparation.clear();OutLineSeparationID.clear();SlicerHeight=tempSliceHight;}///Функция, генерирующая множество контуров - полный слайсиг модели с функцией адаптивногоподхода к высоте слояstatic void GenerateLoopCycleAdaptive(void){///Подготовка к слайсингу и определение параметров слайсингаif (OutLineSeparation.size()>0){cout<<"Count vertex = "<<OutLineSeparation.size()<<endl;}///Создание временных подслоев для определения их степени похожестиfloat tempSliceHight = SlicerHeight;vector <point> tempLoop;vector <int> tempLoopID;vector <point> tempLoop2;vector <int> tempLoopID2;OutLineLoop.clear();OutLineLoopID.clear();///Цикл слайсинга с использованием базовой фунции слайсинга одного слояfor (float height=LayerHeight/2;height<GabariteMaxZ-LayerHeight;height+=LayerHeight){///Создание подслоев для определения их степени похожести.