/*************************************************************************** * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2014 * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include #endif #include "ViewProviderPath.h" #include #include #include #include #include #include #include #include #include #include #include #include #define ARC_MIN_SEGMENTS 20.0 // minimum # segments to interpolate an arc #ifndef M_PI #define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846 /* pi */ #endif #ifndef M_PI_2 #define M_PI_2 1.57079632679489661923 /* pi/2 */ #endif using namespace Gui; using namespace PathGui; using namespace Path; using namespace PartGui; PROPERTY_SOURCE(PathGui::ViewProviderPath, Gui::ViewProviderGeometryObject) ViewProviderPath::ViewProviderPath() :pt0Index(-1),blockPropertyChange(false),edgeStart(-1),coordStart(-1),coordEnd(-1) { ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Path"); unsigned long lcol = hGrp->GetUnsigned("DefaultNormalPathColor",11141375UL); // dark green (0,170,0) float lr,lg,lb; lr = ((lcol >> 24) & 0xff) / 255.0; lg = ((lcol >> 16) & 0xff) / 255.0; lb = ((lcol >> 8) & 0xff) / 255.0; unsigned long mcol = hGrp->GetUnsigned("DefaultPathMarkerColor",1442775295UL); // lime green (85,255,0) float mr,mg,mb; mr = ((mcol >> 24) & 0xff) / 255.0; mg = ((mcol >> 16) & 0xff) / 255.0; mb = ((mcol >> 8) & 0xff) / 255.0; int lwidth = hGrp->GetInt("DefaultPathLineWidth",1); ADD_PROPERTY_TYPE(NormalColor,(lr,lg,lb),"Path",App::Prop_None,"The color of the feed rate moves"); ADD_PROPERTY_TYPE(MarkerColor,(mr,mg,mb),"Path",App::Prop_None,"The color of the markers"); ADD_PROPERTY_TYPE(LineWidth,(lwidth),"Path",App::Prop_None,"The line width of this path"); ADD_PROPERTY_TYPE(ShowNodes,(false),"Path",App::Prop_None,"Turns the display of nodes on/off"); ShowCountConstraints.LowerBound=0; ShowCountConstraints.UpperBound=INT_MAX; ShowCountConstraints.StepSize=1; ShowCount.setConstraints(&ShowCountConstraints); StartIndexConstraints.LowerBound=0; StartIndexConstraints.UpperBound=INT_MAX; StartIndexConstraints.StepSize=1; StartIndex.setConstraints(&StartIndexConstraints); ADD_PROPERTY_TYPE(StartPosition,(Base::Vector3d()),"Show",App::Prop_None,"Tool initial position"); ADD_PROPERTY_TYPE(StartIndex,(0),"Show",App::Prop_None,"The index of first GCode to show"); ADD_PROPERTY_TYPE(ShowCount,(0),"Show",App::Prop_None,"Number of movement GCode to show, 0 means all"); pcLineCoords = new SoCoordinate3(); pcLineCoords->ref(); pcMarkerSwitch = new SoSwitch(); pcMarkerSwitch->ref(); pcMarkerSwitch->whichChild = -1; pcMarkerCoords = new SoCoordinate3(); pcMarkerCoords->ref(); pcMarkerStyle = new SoDrawStyle(); pcMarkerStyle->ref(); pcMarkerStyle->style = SoDrawStyle::POINTS; pcMarkerStyle->pointSize = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View")->GetInt("MarkerSize", 4); pcDrawStyle = new SoDrawStyle(); pcDrawStyle->ref(); pcDrawStyle->style = SoDrawStyle::LINES; pcDrawStyle->lineWidth = LineWidth.getValue(); pcLines = new PartGui::SoBrepEdgeSet(); pcLines->ref(); pcLines->coordIndex.setNum(0); pcLineColor = new SoMaterial; pcLineColor->ref(); pcMatBind = new SoMaterialBinding; pcMatBind->ref(); pcMatBind->value = SoMaterialBinding::OVERALL; pcMarkerColor = new SoBaseColor; pcMarkerColor->ref(); pcArrowSwitch = new SoSwitch(); pcArrowSwitch->ref(); auto pArrowGroup = new SoSkipBoundingGroup; pcArrowTransform = new SoTransform(); pArrowGroup->addChild(pcArrowTransform); auto pArrowScale = new SoShapeScale(); auto pArrow = new SoAxisCrossKit(); pArrow->set("xAxis.appearance.drawStyle", "style INVISIBLE"); pArrow->set("xHead.appearance.drawStyle", "style INVISIBLE"); pArrow->set("yAxis.appearance.drawStyle", "style INVISIBLE"); pArrow->set("yHead.appearance.drawStyle", "style INVISIBLE"); pArrow->set("zAxis.appearance.drawStyle", "style INVISIBLE"); pArrow->set("zHead.transform", "translation 0 0 0"); pArrowScale->setPart("shape", pArrow); pArrowScale->scaleFactor = 1.0f; pArrowGroup->addChild(pArrowScale); pcArrowSwitch->addChild(pArrowGroup); pcArrowSwitch->whichChild = -1; NormalColor.touch(); MarkerColor.touch(); DisplayMode.setStatus(App::Property::Status::Hidden, true); static const char *SelectionStyleEnum[] = {"Shape","BoundBox","None",0}; SelectionStyle.setEnums(SelectionStyleEnum); unsigned long sstyle = hGrp->GetInt("DefaultSelectionStyle",0); SelectionStyle.setValue(sstyle); } ViewProviderPath::~ViewProviderPath() { pcLineCoords->unref(); pcMarkerCoords->unref(); pcMarkerSwitch->unref(); pcDrawStyle->unref(); pcMarkerStyle->unref(); pcLines->unref(); pcLineColor->unref(); pcMatBind->unref(); pcMarkerColor->unref(); pcArrowSwitch->unref(); } void ViewProviderPath::attach(App::DocumentObject *pcObj) { inherited::attach(pcObj); // Draw trajectory lines SoSeparator* linesep = new SoSeparator; linesep->addChild(pcLineColor); linesep->addChild(pcMatBind); linesep->addChild(pcDrawStyle); linesep->addChild(pcLineCoords); linesep->addChild(pcLines); // Draw markers SoSeparator* markersep = new SoSeparator; SoPointSet* marker = new SoPointSet; markersep->addChild(pcMarkerColor); markersep->addChild(pcMarkerCoords); markersep->addChild(pcMarkerStyle); markersep->addChild(marker); pcMarkerSwitch->addChild(markersep); SoSeparator* pcPathRoot = new SoSeparator(); pcPathRoot->addChild(pcMarkerSwitch); pcPathRoot->addChild(linesep); pcPathRoot->addChild(pcArrowSwitch); addDisplayMaskMode(pcPathRoot, "Waypoints"); } bool ViewProviderPath::useNewSelectionModel(void) const { return SelectionStyle.getValue()!=2; } void ViewProviderPath::setDisplayMode(const char* ModeName) { if ( strcmp("Waypoints",ModeName)==0 ) setDisplayMaskMode("Waypoints"); inherited::setDisplayMode( ModeName ); } std::vector ViewProviderPath::getDisplayModes(void) const { std::vector StrList; StrList.push_back("Waypoints"); return StrList; } std::string ViewProviderPath::getElement(const SoDetail* detail) const { if(edgeStart>=0 && detail && detail->getTypeId() == SoLineDetail::getClassTypeId()) { const SoLineDetail* line_detail = static_cast(detail); int index = line_detail->getLineIndex()+edgeStart; if(index>=0 && index<(int)edge2Command.size()) { index = edge2Command[index]; Path::Feature* pcPathObj = static_cast(pcObject); const Toolpath &tp = pcPathObj->Path.getValue(); if(index<(int)tp.getSize()) { std::stringstream str; str << index+1 << " " << tp.getCommand(index).toGCode(6,false); pt0Index = line_detail->getPoint0()->getCoordinateIndex(); if(pt0Index<0 || pt0Index>=pcLineCoords->point.getNum()) pt0Index = -1; return str.str(); } } } pt0Index = -1; pcArrowSwitch->whichChild = -1; return std::string(); } SoDetail* ViewProviderPath::getDetail(const char* subelement) const { int index = std::atoi(subelement); SoDetail* detail = 0; if (index>0 && index<=(int)command2Edge.size()) { index = command2Edge[index-1]; if(index>=0 && edgeStart>=0 && edgeStart<=index) { detail = new SoLineDetail(); static_cast(detail)->setLineIndex(index-edgeStart); } } return detail; } void ViewProviderPath::onSelectionChanged(const Gui::SelectionChanges& msg) { if(msg.Type == Gui::SelectionChanges::SetPreselect && msg.pSubName && pt0Index >= 0 && getObject() && getObject()->getDocument()) { const char *docName = getObject()->getDocument()->getName(); const char *objName = getObject()->getNameInDocument(); if(docName && objName && strcmp(msg.pDocName,docName)==0 && strcmp(msg.pObjectName,objName)==0) { Path::Feature* pcPathObj = static_cast(pcObject); Base::Vector3d pt = pcPathObj->Placement.getValue().inverse().toMatrix()* Base::Vector3d(msg.x,msg.y,msg.z); const SbVec3f &ptTo = *pcLineCoords->point.getValues(pt0Index); SbVec3f ptFrom(pt.x,pt.y,pt.z); if(ptFrom != ptTo) { pcArrowTransform->pointAt(ptFrom,ptTo); pcArrowSwitch->whichChild = 0; return; } } } pcArrowSwitch->whichChild = -1; } void ViewProviderPath::onChanged(const App::Property* prop) { if(blockPropertyChange) return; if (prop == &LineWidth) { pcDrawStyle->lineWidth = LineWidth.getValue(); } else if (prop == &NormalColor) { if (colorindex.size() > 0 && coordStart>=0 && coordStart<(int)colorindex.size()) { const App::Color& c = NormalColor.getValue(); ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Path"); unsigned long rcol = hGrp->GetUnsigned("DefaultRapidPathColor",2852126975UL); // dark red (170,0,0) float rr,rg,rb; rr = ((rcol >> 24) & 0xff) / 255.0; rg = ((rcol >> 16) & 0xff) / 255.0; rb = ((rcol >> 8) & 0xff) / 255.0; unsigned long pcol = hGrp->GetUnsigned("DefaultProbePathColor",4293591295UL); // yellow (255,255,5) float pr,pg,pb; pr = ((pcol >> 24) & 0xff) / 255.0; pg = ((pcol >> 16) & 0xff) / 255.0; pb = ((pcol >> 8) & 0xff) / 255.0; pcMatBind->value = SoMaterialBinding::PER_PART; // resizing and writing the color vector: int count = coordEnd-coordStart; if(count > (int)colorindex.size()-coordStart) count = colorindex.size()-coordStart; pcLineColor->diffuseColor.setNum(count); SbColor* colors = pcLineColor->diffuseColor.startEditing(); for(int i=0;idiffuseColor.finishEditing(); } } else if (prop == &MarkerColor) { const App::Color& c = MarkerColor.getValue(); pcMarkerColor->rgb.setValue(c.r,c.g,c.b); } else if(prop == &ShowNodes) { pcMarkerSwitch->whichChild = ShowNodes.getValue()?0:-1; } else if (prop == &ShowCount || prop==&StartIndex) { bool vis = isShow(); if (vis) hide(); updateVisual(); if (vis) show(); } else if (prop == &StartPosition) { if(pcLineCoords->point.getNum()){ const Base::Vector3d &pt = StartPosition.getValue(); pcLineCoords->point.set1Value(0,pt.x,pt.y,pt.z); pcMarkerCoords->point.set1Value(0,pt.x,pt.y,pt.z); } } else { inherited::onChanged(prop); if(prop == &SelectionStyle && SelectionStyle.getValue()==2) hideSelection(); } } void ViewProviderPath::showBoundingBox(bool show) { if(show) { if(!pcLineCoords->point.getNum()) return; } inherited::showBoundingBox(show); } unsigned long ViewProviderPath::getBoundColor() const { ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Path"); if(SelectionStyle.getValue() == 0 || !Selectable.getValue()) return hGrp->GetUnsigned("DefaultBBoxNormalColor",4294967295UL); // white (255,255,255) else return hGrp->GetUnsigned("DefaultBBoxSelectionColor",0xc8ffff00UL); // rgb(0,85,255) } void ViewProviderPath::updateShowConstraints() { Path::Feature* pcPathObj = static_cast(pcObject); const Toolpath &tp = pcPathObj->Path.getValue(); StartIndexConstraints.UpperBound = tp.getSize(); if (StartIndex.getValue() >= (long)tp.getSize()) { int start = ((int)tp.getSize())-ShowCount.getValue(); if(start>=(int)tp.getSize()) start=tp.getSize()-1; if(start<0) start = 0; blockPropertyChange = true; StartIndex.setValue(start); blockPropertyChange = false; StartIndex.purgeTouched(); } StartIndexConstraints.StepSize = ShowCount.getValue()>2?ShowCount.getValue()-2:1; } void ViewProviderPath::updateData(const App::Property* prop) { Path::Feature* pcPathObj = static_cast(pcObject); if(prop == &pcPathObj->Path) { updateVisual(true); return; } inherited::updateData(prop); } void ViewProviderPath::hideSelection() { // Clear selection SoSelectionElementAction saction(Gui::SoSelectionElementAction::None); saction.apply(pcLines); // Clear highlighting SoHighlightElementAction haction; haction.apply(pcLines); // Hide arrow pcArrowSwitch->whichChild = -1; } Base::Vector3d compensateRotation(const Base::Vector3d &pt, const Base::Rotation &rot, const Base::Vector3d ¢er) { Base::Vector3d ptRotated; rot.multVec(pt - center, ptRotated); return ptRotated + center; } Base::Rotation yawPitchRoll(double a, double b, double c) { Base::Rotation rot; rot.setYawPitchRoll(-c, b, -a); return rot; } void ViewProviderPath::updateVisual(bool rebuild) { hideSelection(); updateShowConstraints(); pcLines->coordIndex.deleteValues(0); if(rebuild) { pcLineCoords->point.deleteValues(0); pcMarkerCoords->point.deleteValues(0); command2Edge.clear(); edge2Command.clear(); edgeIndices.clear(); Path::Feature* pcPathObj = static_cast(pcObject); const Toolpath &tp = pcPathObj->Path.getValue(); if(tp.getSize()==0) { return; } ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Part"); float deviation = hGrp->GetFloat("MeshDeviation",0.2); std::deque points; std::deque markers; Base::Vector3d rotCenter = tp.getCenter(); Base::Vector3d last(StartPosition.getValue()); Base::Rotation lrot; double A = 0.0; double B = 0.0; double C = 0.0; colorindex.clear(); bool absolute = true; bool absolutecenter = false; // for mapping the coordinates to XY plane double Base::Vector3d::*pz = &Base::Vector3d::z; command2Edge.resize(tp.getSize(),-1); points.push_back(last); markers.push_back(last); // startpoint of path for (unsigned int i = 0; i < tp.getSize(); i++) { const Path::Command &cmd = tp.getCommand(i); const std::string &name = cmd.Name; Base::Vector3d next = cmd.getPlacement().getPosition(); double a = A; double b = B; double c = C; if (!absolute) next = last + next; if (!cmd.has("X")) next.x = last.x; if (!cmd.has("Y")) next.y = last.y; if (!cmd.has("Z")) next.z = last.z; if ( cmd.has("A")) a = cmd.getValue("A"); if ( cmd.has("B")) b = cmd.getValue("B"); if ( cmd.has("C")) c = cmd.getValue("C"); Base::Rotation nrot = yawPitchRoll(a, b, c); Base::Vector3d rnext = compensateRotation(next, nrot, rotCenter); if ( (name == "G0") || (name == "G00") || (name == "G1") || (name == "G01") ) { // straight line int color = ((name == "G0") || (name == "G00")) ? 0 : 1; if (nrot != lrot) { double amax = std::max(fmod(fabs(a - A), 360), std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))); double angle = amax / 180 * M_PI; int segments = std::max(ARC_MIN_SEGMENTS, 3.0/(deviation/angle)); double da = (a - A) / segments; double db = (b - B) / segments; double dc = (c - C) / segments; Base::Vector3d dnext = (next - last) / segments; for (int j = 1; j < segments; j++) { Base::Vector3d inter = last + dnext * j; Base::Rotation rot = yawPitchRoll(A + da*j, B + db*j, C + dc*j); Base::Vector3d rinter = compensateRotation(inter, rot, rotCenter); points.push_back(rinter); colorindex.push_back(color); } } points.push_back(rnext); markers.push_back(rnext); // endpoint colorindex.push_back(color); // std color command2Edge[i] = edgeIndices.size(); edgeIndices.push_back(points.size()); edge2Command.push_back(i); last = next; A = a; B = b; C = c; lrot = nrot; } else if ( (name == "G2") || (name == "G02") || (name == "G3") || (name == "G03") ) { // arc Base::Vector3d norm; Base::Vector3d center; if ( (name == "G2") || (name == "G02") ) norm.*pz = -1.0; else norm.*pz = 1.0; if (absolutecenter) center = cmd.getCenter(); else center = (last + cmd.getCenter()); Base::Vector3d next0(next); next0.*pz = 0.0; Base::Vector3d last0(last); last0.*pz = 0.0; Base::Vector3d center0(center); center0.*pz = 0.0; //double radius = (last - center).Length(); double angle = (next0 - center0).GetAngle(last0 - center0); // GetAngle will always return the minor angle. Switch if needed Base::Vector3d anorm = (last0 - center0) % (next0 - center0); if (anorm.*pz < 0) { if(name == "G3" || name == "G03") angle = M_PI * 2 - angle; } else if(anorm.*pz > 0) { if(name == "G2" || name == "G02") angle = M_PI * 2 - angle; } else if (angle == 0) angle = M_PI * 2; double amax = std::max(fmod(fabs(a - A), 360), std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))); int segments = std::max(ARC_MIN_SEGMENTS, 3.0/(deviation/std::max(angle, amax))); //we use a rather simple rule here, provisorily double dZ = (next.*pz - last.*pz)/segments; //How far each segment will helix in Z double dangle = angle/segments; double da = (a - A) / segments; double db = (b - B) / segments; double dc = (c - C) / segments; for (int j = 1; j < segments; j++) { Base::Vector3d inter; Base::Rotation rot(norm, dangle*j); rot.multVec((last0 - center0), inter); inter.*pz = last.*pz + dZ * j; //Enable displaying helices Base::Rotation arot = yawPitchRoll(A + da*j, B + db*j, C + dc*j); Base::Vector3d rinter = compensateRotation(center0 + inter, arot, rotCenter); points.push_back(rinter); colorindex.push_back(1); } points.push_back(rnext); markers.push_back(rnext); // endpoint markers.push_back(center); // add a marker at center too colorindex.push_back(1); command2Edge[i] = edgeIndices.size(); edgeIndices.push_back(points.size()); edge2Command.push_back(i); last = next; A = a; B = b; C = c; lrot = nrot; } else if (name == "G90") { // absolute mode absolute = true; } else if (name == "G91") { // relative mode absolute = false; } else if (name == "G90.1") { // absolute mode absolutecenter = true; } else if (name == "G91.1") { // relative mode absolutecenter = false; } else if ((name=="G81")||(name=="G82")||(name=="G83")||(name=="G84")||(name=="G85")||(name=="G86")||(name=="G89")){ // drill,tap,bore double r = 0; if (cmd.has("R")) r = cmd.getValue("R"); Base::Vector3d p1(next); p1.*pz = last.*pz; if (nrot != lrot) { double amax = std::max(fmod(fabs(a - A), 360), std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))); double angle = amax / 180 * M_PI; int segments = std::max(ARC_MIN_SEGMENTS, 3.0/(deviation/angle)); double da = (a - A) / segments; double db = (b - B) / segments; double dc = (c - C) / segments; Base::Vector3d dnext = (p1 - last) / segments; for (int j = 1; j < segments; j++) { Base::Vector3d inter = last + dnext * j; Base::Rotation rot = yawPitchRoll(A + da*j, B + db*j, C + dc*j); Base::Vector3d rinter = compensateRotation(inter, rot, rotCenter); points.push_back(rinter); colorindex.push_back(0); } } Base::Vector3d p1r = compensateRotation(p1, nrot, rotCenter); points.push_back(p1r); markers.push_back(p1r); colorindex.push_back(0); Base::Vector3d p2(next); p2.*pz = r; Base::Vector3d p2r = compensateRotation(p2, nrot, rotCenter); points.push_back(p2r); markers.push_back(p2r); colorindex.push_back(0); points.push_back(rnext); markers.push_back(rnext); colorindex.push_back(1); double q; if (cmd.has("Q")) { q = cmd.getValue("Q"); if (q>0) { Base::Vector3d temp(next); for(temp.*pz=r;temp.*pz>next.*pz;temp.*pz-=q) { Base::Vector3d pr = compensateRotation(temp, nrot, rotCenter); markers.push_back(pr); } } } Base::Vector3d p3(next); p3.*pz = last.*pz; Base::Vector3d p3r = compensateRotation(p3, nrot, rotCenter); points.push_back(p3r); markers.push_back(p2r); colorindex.push_back(0); command2Edge[i] = edgeIndices.size(); edgeIndices.push_back(points.size()); edge2Command.push_back(i); last = p3; A = a; B = b; C = c; lrot = nrot; } else if ((name=="G38.2")||(name=="38.3")||(name=="G38.4")||(name=="G38.5")){ // Straight probe Base::Vector3d p1(next.x,next.y,last.z); points.push_back(p1); colorindex.push_back(0); points.push_back(next); colorindex.push_back(2); Base::Vector3d p3(next.x,next.y,last.z); points.push_back(p3); colorindex.push_back(0); command2Edge[i] = edgeIndices.size(); edgeIndices.push_back(points.size()); edge2Command.push_back(i); } else if(name=="G17") { pz = &Base::Vector3d::z; } else if(name=="G18") { pz = &Base::Vector3d::y; } else if(name=="G19") { pz = &Base::Vector3d::x; } } if (!edgeIndices.empty()) { pcLineCoords->point.setNum(points.size()); SbVec3f* verts = pcLineCoords->point.startEditing(); int i=0; for(const auto &pt : points) verts[i++].setValue(pt.x,pt.y,pt.z); pcLineCoords->point.finishEditing(); pcMarkerCoords->point.setNum(markers.size()); for(unsigned int i=0;ipoint.set1Value(i,markers[i].x,markers[i].y,markers[i].z); recomputeBoundingBox(); } } // count = index + separators edgeStart = -1; int i; for(i=StartIndex.getValue();i<(int)command2Edge.size();++i) if((edgeStart=command2Edge[i])>=0) break; if(edgeStart<0) return; if(i!=StartIndex.getValue() && StartIndex.getValue()!=0) { blockPropertyChange = true; StartIndex.setValue(i); blockPropertyChange = false; StartIndex.purgeTouched(); } int edgeEnd = edgeStart+ShowCount.getValue(); if(edgeEnd==edgeStart || edgeEnd>(int)edgeIndices.size()) edgeEnd = edgeIndices.size(); // coord index start coordStart = edgeStart==0?0:(edgeIndices[edgeStart-1]-1); coordEnd = edgeIndices[edgeEnd-1]; // count = coord indices + index separators int count = coordEnd-coordStart+2*(edgeEnd-edgeStart-1)+1; pcLines->coordIndex.setNum(count); int32_t *idx = pcLines->coordIndex.startEditing(); i=0; int start = coordStart; for(int e=edgeStart;e!=edgeEnd;++e) { for(int end=edgeIndices[e];startcoordIndex.finishEditing(); assert(i==count); NormalColor.touch(); } void ViewProviderPath::recomputeBoundingBox() { // update the boundbox double MinX,MinY,MinZ,MaxX,MaxY,MaxZ; MinX = 999999999.0; MinY = 999999999.0; MinZ = 999999999.0; MaxX = -999999999.0; MaxY = -999999999.0; MaxZ = -999999999.0; Path::Feature* pcPathObj = static_cast(pcObject); Base::Placement pl = *(&pcPathObj->Placement.getValue()); Base::Vector3d pt; for (int i=1;ipoint.getNum();i++) { pt.x = pcLineCoords->point[i].getValue()[0]; pt.y = pcLineCoords->point[i].getValue()[1]; pt.z = pcLineCoords->point[i].getValue()[2]; pl.multVec(pt,pt); if (pt.x < MinX) MinX = pt.x; if (pt.y < MinY) MinY = pt.y; if (pt.z < MinZ) MinZ = pt.z; if (pt.x > MaxX) MaxX = pt.x; if (pt.y > MaxY) MaxY = pt.y; if (pt.z > MaxZ) MaxZ = pt.z; } pcBoundingBox->minBounds.setValue(MinX, MinY, MinZ); pcBoundingBox->maxBounds.setValue(MaxX, MaxY, MaxZ); } QIcon ViewProviderPath::getIcon() const { return Gui::BitmapFactory().pixmap("Path-Toolpath"); } // Python object ----------------------------------------------------------------------- namespace Gui { /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(PathGui::ViewProviderPathPython, PathGui::ViewProviderPath) /// @endcond // explicit template instantiation template class PathGuiExport ViewProviderPythonFeatureT; }