コード例 #1
0
ファイル: CxfFont.cpp プロジェクト: Blokkendoos/heekscad
void VectorFont::Glyph::GlyphLine::glCommands(
	const gp_Pnt & starting_point,
	const bool select,
	const bool marked,
	const bool no_color,
	COrientationModifier *pOrientationModifier,
	gp_Trsf transformation,
	const float width ) const
{
	gp_Pnt from( starting_point );
	gp_Pnt to( starting_point );

    from.SetX( starting_point.X() + m_x1);
	from.SetY( starting_point.Y() + m_y1);
	from.SetZ( starting_point.Z() );

	to.SetX( starting_point.X() + m_x2);
	to.SetY( starting_point.Y() + m_y2);
	to.SetZ( starting_point.Z() );

	if (pOrientationModifier)
	{
	    from = pOrientationModifier->Transform(transformation, starting_point.Distance(gp_Pnt(0.0,0.0,0.0)), from, width );
	    to = pOrientationModifier->Transform(transformation, starting_point.Distance(gp_Pnt(0.0,0.0,0.0)), to, width );
	}

	glBegin(GL_LINE_STRIP);
	glVertex3d(from.X(), from.Y(), from.Z());
	glVertex3d(to.X(), to.Y(), to.Z());
	glEnd();
} // End glCommands() method
コード例 #2
0
bool CTiglAbstractGeometricComponent::GetIsOn(const gp_Pnt& pnt) 
{
    const TopoDS_Shape& segmentShape = GetLoft()->Shape();

    // fast check with bounding box
    Bnd_Box boundingBox;
    BRepBndLib::Add(segmentShape, boundingBox);

    Standard_Real xmin, xmax, ymin, ymax, zmin, zmax;
    boundingBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);

    if (pnt.X() < xmin || pnt.X() > xmax ||
        pnt.Y() < ymin || pnt.Y() > ymax ||
        pnt.Z() < zmin || pnt.Z() > zmax) {

        return false;
    }

    double tolerance = 0.03; // 3cm

    BRepClass3d_SolidClassifier classifier;
    classifier.Load(segmentShape);
    classifier.Perform(pnt, tolerance);
    if ((classifier.State() == TopAbs_IN) || (classifier.State() == TopAbs_ON)) {
        return true;
    }
    else {
        return false;
    }
}
コード例 #3
0
 bool operator()(const gp_Pnt& p1,
                 const gp_Pnt& p2) const
 {
     if (fabs(p1.X() - p2.X()) > Precision::Confusion())
         return p1.X() < p2.X();
     if (fabs(p1.Y() - p2.Y()) > Precision::Confusion())
         return p1.Y() < p2.Y();
     if (fabs(p1.Z() - p2.Z()) > Precision::Confusion())
         return p1.Z() < p2.Z();
     return false; // points are considered to be equal
 }
コード例 #4
0
ファイル: rs274emc.cpp プロジェクト: play113/swer
bool rs274emc::comparePoints(gp_Pnt a,gp_Pnt b)
{
    bool result=0, xIdent=0, yIdent=0, zIdent=0;
    
    xIdent=!(a.X()-b.X());
    yIdent=!(a.Y()-b.Y());
    zIdent=!(a.Z()-b.Z());
    
    if (xIdent && yIdent && zIdent)
	result=1;
    return result;
}
コード例 #5
0
//is p1 "less than" p2?
bool ImpExpDxfWrite::gp_PntCompare(gp_Pnt p1, gp_Pnt p2) 
{
    bool result = false;
    if (!(p1.IsEqual(p2,Precision::Confusion()))) {                       //ie v1 != v2
        if (!(fabs(p1.X() - p2.X()) < Precision::Confusion())) {          // x1 != x2
            result = p1.X() < p2.X();        
        } else if (!(fabs(p1.Y() - p2.Y()) < Precision::Confusion())) {   // y1 != y2
            result = p1.Y() < p2.Y();
        } else {
            result = p1.Z() < p2.Z();
        }
    }
    return result;
}
コード例 #6
0
ファイル: GuideRectODL.cpp プロジェクト: litao1009/SimpleRoom
void CGuideRectODL::SetTopStopPos( gp_Pnt ptStop )
{
	SetIsTopCreating(false);
	CBaseODL::SetTopStopPos(ptStop);
	m_rtArea.Width = static_cast<Gdiplus::REAL>(abs(m_ptTopStart.X() - ptStop.X()));
	m_rtArea.Height = static_cast<Gdiplus::REAL>(abs(m_ptTopStart.Z() - ptStop.Z()));
}
コード例 #7
0
ファイル: GuideRectODL.cpp プロジェクト: litao1009/SimpleRoom
void CGuideRectODL::SetTopCurrentPos( gp_Pnt ptCurrent )
{
	CBaseODL::SetTopCurrentPos(ptCurrent);
	
	m_rtArea.Width = static_cast<Gdiplus::REAL>(abs(m_ptTopStart.X() - ptCurrent.X()));
	m_rtArea.Height = static_cast<Gdiplus::REAL>(abs(m_ptTopStart.Z() - ptCurrent.Z()));
	if (m_ptTopStart.X()>ptCurrent.X())
	{
		m_rtArea.X = static_cast<Gdiplus::REAL>(ptCurrent.X());
		
	}
	if ( ptCurrent.Z()<m_ptTopStart.Z())
	{
		m_rtArea.Y= static_cast<Gdiplus::REAL>(ptCurrent.Z());
	}
}
コード例 #8
0
ファイル: GuideRectODL.cpp プロジェクト: litao1009/SimpleRoom
void CGuideRectODL::SetTopStartPos( gp_Pnt ptStart )
{
	SetIsTopCreating(true);
	CBaseODL::SetTopStartPos(ptStart);
	m_rtArea.X= static_cast<Gdiplus::REAL>(ptStart.X());
	m_rtArea.Y = static_cast<Gdiplus::REAL>(ptStart.Z());
}
コード例 #9
0
ファイル: CxfFont.cpp プロジェクト: Blokkendoos/heekscad
std::list<gp_Pnt> VectorFont::Glyph::GlyphArc::Interpolate(const gp_Pnt & location, const unsigned int number_of_points ) const
{
	std::list<gp_Pnt> points;

	gp_Pnt origin(location);
	origin.SetX( origin.X() + m_xcentre );
	origin.SetY( origin.Y() + m_ycentre );

	double start_angle = m_start_angle;
	double end_angle = m_end_angle;

	if (start_angle > end_angle)
	{
		end_angle += (2 * M_PI);
	}

	double increment = (end_angle - start_angle) / number_of_points;

	gp_Dir z_direction( 0, 0, 1 );
	for (double angle = start_angle; angle <= end_angle; angle += increment)
	{
		gp_Pnt point( location.X() + m_xcentre + m_radius, location.Y() + m_ycentre, location.Z() );
		gp_Trsf rotation_matrix;
		rotation_matrix.SetRotation( gp_Ax1(origin, z_direction), angle );
		point.Transform(rotation_matrix);
		points.push_back(point);
	}

	return(points);
}
コード例 #10
0
point3D gPntTopoint3D(gp_Pnt& p)
{ 
   point3D result;
   result.x = p.X();
   result.y = p.Y();
   result.z = p.Z();
   return result;
}
コード例 #11
0
//!set up a hidden line remover and project a shape with it
void GeometryObject::projectShape(const TopoDS_Shape& input,
                             const gp_Pnt& inputCenter,
                             const Base::Vector3d& direction)
{
    // Clear previous Geometry
    clear();
    Base::Vector3d origin(inputCenter.X(),inputCenter.Y(),inputCenter.Z());
    gp_Ax2 viewAxis = getViewAxis(origin,direction);
    auto start = chrono::high_resolution_clock::now();

    Handle_HLRBRep_Algo brep_hlr = NULL;
    try {
        brep_hlr = new HLRBRep_Algo();
        brep_hlr->Add(input, m_isoCount);
        HLRAlgo_Projector projector( viewAxis );
        brep_hlr->Projector(projector);
        brep_hlr->Update();
        brep_hlr->Hide();
    }
    catch (...) {
        Standard_Failure::Raise("GeometryObject::projectShape - error occurred while projecting shape");
    }
    auto end   = chrono::high_resolution_clock::now();
    auto diff  = end - start;
    double diffOut = chrono::duration <double, milli> (diff).count();
    Base::Console().Log("TIMING - %s GO spent: %.3f millisecs in HLRBRep_Algo & co\n",m_parentName.c_str(),diffOut);

    try {
        HLRBRep_HLRToShape hlrToShape(brep_hlr);

        visHard    = hlrToShape.VCompound();
        visSmooth  = hlrToShape.Rg1LineVCompound();
        visSeam    = hlrToShape.RgNLineVCompound();
        visOutline = hlrToShape.OutLineVCompound();
        visIso     = hlrToShape.IsoLineVCompound();
        hidHard    = hlrToShape.HCompound();
        hidSmooth  = hlrToShape.Rg1LineHCompound();
        hidSeam    = hlrToShape.RgNLineHCompound();
        hidOutline = hlrToShape.OutLineHCompound();
        hidIso     = hlrToShape.IsoLineHCompound();

//need these 3d curves to prevent "zero edges" later
        BRepLib::BuildCurves3d(visHard);
        BRepLib::BuildCurves3d(visSmooth);
        BRepLib::BuildCurves3d(visSeam);
        BRepLib::BuildCurves3d(visOutline);
        BRepLib::BuildCurves3d(visIso);
        BRepLib::BuildCurves3d(hidHard);
        BRepLib::BuildCurves3d(hidSmooth);
        BRepLib::BuildCurves3d(hidSeam);
        BRepLib::BuildCurves3d(hidOutline);
        BRepLib::BuildCurves3d(hidIso);
    }
    catch (...) {
        Standard_Failure::Raise("GeometryObject::projectShape - error occurred while extracting edges");
    }

}
コード例 #12
0
ファイル: FastCurves.cpp プロジェクト: Blokkendoos/heekscad
std::vector<RayIntersection> FastArc::RayIntersects(gp_Pnt p)
{
	std::vector<RayIntersection> ret;

	double y = p.Y() - C.Y();
	if(fabs(y) > rad)
		return ret;

	double x1 = sqrt(rad*rad - y*y);
	double x2 = x1+C.X();
	x1 = C.X()-x1;

	if(x1 < p.X())
		ret.push_back(RayIntersection(GetU(x1,p.Y()),gp_Pnt(x1,p.Y(),0),false,false));
	if(x2 < p.X())
		ret.push_back(RayIntersection(GetU(x2,p.Y()),gp_Pnt(x2,p.Y(),0),false,false));
	return ret;
}
コード例 #13
0
ファイル: FastCurves.cpp プロジェクト: Blokkendoos/heekscad
FastArc::FastArc(gp_Pnt A,gp_Pnt B, gp_Pnt C, bool cw, gp_Circ circ)
{
	if(!cw)
	{
		gp_Pnt temp = A;
		A = B;
		B = temp;
		circ.SetAxis(circ.Axis().Reversed());
	}


	this->A = A;
	this->B = B;
	this->C = C;
	this->cw = cw;
	this->m_circ = circ;
	this->m_flipped = false;


	a1 = atan2(A.Y()-C.Y(), A.X()-C.X());
	a2 = atan2(B.Y()-C.Y(), B.X()-C.X());
	if(a2<a1)
		a2+=2*M_PI;

	da = a2 - a1;
	rad = C.Distance(A);
	//TODO: compute how far apart the angles are, signed!
	//da = fmod(a2-a1,2*Pi);

#ifdef CHECKFASTARC
	double tax = GetXatU(0);
	double tay = GetYatU(0);
	double tbx = GetXatU(1);
	double tby = GetYatU(1);
	if(tax != A.X() || tay != A.Y() || tbx != B.X() || tby != B.Y())
	{
		int x=0;
		x++;
	}
#endif
}
コード例 #14
0
ファイル: ISession_Text.cpp プロジェクト: DLR-SC/tigl
ISession_Text::ISession_Text
                 (const TCollection_AsciiString& aText, 
                  gp_Pnt&                        aPoint,
                  const Quantity_PlaneAngle      anAngle,     // = 0.0
                  const Standard_Real            aslant,      // = 0.0
                  const Standard_Integer         aColorIndex, // = 0
                  const Standard_Integer         aFontIndex,  // = 1
                  const Quantity_Factor          aScale)      // = 1
                  :AIS_InteractiveObject(),MyText(aText),MyX(aPoint.X()),MyY(aPoint.Y()),MyZ(aPoint.Z()),
                  MyAngle(anAngle),MySlant(aslant),MyFontIndex(aFontIndex),
                  MyColorIndex(aColorIndex),MyScale(aScale),MyWidth(0),MyHeight(0)
{}
コード例 #15
0
ファイル: SkyODL.cpp プロジェクト: litao1009/SimpleRoom
void CSkyODL::OnTopMoving(const gp_Pnt& stInfo)
{
	CBaseODL::OnTopMoving(stInfo);
	m_arrMovingTopPoint.clear();
	//修改所有点的最终位置
	for (auto& curPnt : m_arrTopPoint)
	{
		gp_Pnt pt(curPnt.X() + stInfo.X(), 
			curPnt.Y() + stInfo.Y(),
			curPnt.Z() + stInfo.Z()
			);
		m_arrMovingTopPoint.push_back(pt);
	}
}
コード例 #16
0
//=======================================================================
//function : FindBestPoint
//purpose  : Auxilare for Compute()
//           V - normal to (P1,P2,PC)
//=======================================================================
static gp_Pnt FindBestPoint(const gp_Pnt& P1, const gp_Pnt& P2,
                            const gp_Pnt& PC, const gp_Vec& V)
{
  double a = P1.Distance(P2);
  double b = P1.Distance(PC);
  double c = P2.Distance(PC);
  if( a < (b+c)/2 )
    return PC;
  else {
    // find shift along V in order to a became equal to (b+c)/2
    double shift = sqrt( a*a + (b*b-c*c)*(b*b-c*c)/16/a/a - (b*b+c*c)/2 );
    gp_Dir aDir(V);
    gp_Pnt Pbest( PC.X() + aDir.X()*shift,  PC.Y() + aDir.Y()*shift,
                  PC.Z() + aDir.Z()*shift );
    return Pbest;
  }
}
コード例 #17
0
ファイル: FastCurves.cpp プロジェクト: Blokkendoos/heekscad
std::vector<RayIntersection> FastLine::RayIntersects(gp_Pnt pnt)
{
	std::vector<RayIntersection> ret;
	//If this line is significantly horizontal, there is nothing good
	//we can do here
	if(B.Y() < A.Y() + TOLERANCE/4 && B.Y() > A.Y() - TOLERANCE/4)
		return ret;

	if((pnt.Y() < B.Y() + TOLERANCE && pnt.Y() > A.Y() - TOLERANCE)||
		(pnt.Y() > B.Y() - TOLERANCE && pnt.Y() < A.Y() + TOLERANCE))
	{
		if(fabs(A.Y() - B.Y()) < TOLERANCE)
			return ret;
		double u = (pnt.Y() - A.Y())/(B.Y()-A.Y());
		double x = GetXatU(u);
		if(x < pnt.X())
			ret.push_back(RayIntersection(u,gp_Pnt(x,pnt.Y(),0),false,false));
	}
	return ret;
}
コード例 #18
0
ファイル: HPoint.cpp プロジェクト: DavidNicholls/heekscad
/* static */ gp_Pnt HPoint::GetOffset(gp_Pnt location)
{
	wxString message(_("Enter offset in X,Y,Z format (with commas between them)"));
	wxString caption(_("Apply Offset To Selected Location"));
	wxString default_value(_T("0,0,0"));

	wxString value = wxGetTextFromUser(message, caption, default_value);
	wxStringTokenizer tokens(value,_T(":,\t\n"));

	for (int i=0; i<3; i++)
	{
		if (tokens.HasMoreTokens())
		{
			double offset = 0.0;
			wxString token = tokens.GetNextToken();
			wxString evaluated_version;
			if (PropertyDouble::EvaluateWithPython( NULL, token, evaluated_version ))
			{
				evaluated_version.ToDouble(&offset);
				offset *= wxGetApp().m_view_units;
				switch(i)
				{
				case 0:
					location.SetX( location.X() + offset );
					break;

				case 1:
					location.SetY( location.Y() + offset );
					break;

				case 2:
					location.SetZ( location.Z() + offset );
					break;
				}

			}
		}
	}

	return(location);
}
コード例 #19
0
void gPntToTuple(double* result, gp_Pnt& p)
{
   result[0] = p.X();
   result[1] = p.Y();
   result[2] = p.Z();
}
コード例 #20
0
ファイル: Point.cpp プロジェクト: pippijn/robotnavi
Point::Point(gp_Pnt pnt){
	x = pnt.X();
	y = pnt.Y();
	z = pnt.Z();
}
コード例 #21
0
//! \relates MathTools
gp_Pnt operator+(const gp_Pnt& p, const gp_Vec& v)
{
  return gp_Pnt(p.X() + v.X(), p.Y() + v.Y(), p.Z() + v.Z());
}
コード例 #22
0
//! \relates MathTools
gp_Vec operator-(const gp_Pnt& p1, const gp_Pnt& p2)
{
  return gp_Vec(p2.X() - p1.X(), p2.Y() - p1.Y(), p2.Z() - p1.Z());
}
コード例 #23
0
//! project a single face using HLR - used for section faces
TopoDS_Face DrawViewSection::projectFace(const TopoDS_Shape &face,
                                     gp_Pnt faceCenter,
                                     const Base::Vector3d &direction)
{
    if(face.IsNull()) {
        throw Base::Exception("DrawViewSection::projectFace - input Face is NULL");
    }

    Base::Vector3d origin(faceCenter.X(),faceCenter.Y(),faceCenter.Z());
    gp_Ax2 viewAxis = TechDrawGeometry::getViewAxis(origin,direction);

    HLRBRep_Algo *brep_hlr = new HLRBRep_Algo();
    brep_hlr->Add(face);
    HLRAlgo_Projector projector( viewAxis );
    brep_hlr->Projector(projector);
    brep_hlr->Update();
    brep_hlr->Hide();

    HLRBRep_HLRToShape hlrToShape(brep_hlr);
    TopoDS_Shape hardEdges = hlrToShape.VCompound();
//    TopoDS_Shape outEdges = hlrToShape.OutLineVCompound();
    std::vector<TopoDS_Edge> faceEdges;
    TopExp_Explorer expl(hardEdges, TopAbs_EDGE);
    int i;
    for (i = 1 ; expl.More(); expl.Next(),i++) {
        const TopoDS_Edge& edge = TopoDS::Edge(expl.Current());
        if (edge.IsNull()) {
            Base::Console().Log("INFO - DVS::projectFace - hard edge: %d is NULL\n",i);
            continue;
        }
        faceEdges.push_back(edge);
    }
    //TODO: verify that outline edges aren't required
    //if edge is both hard & outline, it will be duplicated? are hard edges enough?
//    TopExp_Explorer expl2(outEdges, TopAbs_EDGE);
//    for (i = 1 ; expl2.More(); expl2.Next(),i++) {
//        const TopoDS_Edge& edge = TopoDS::Edge(expl2.Current());
//        if (edge.IsNull()) {
//            Base::Console().Log("INFO - GO::projectFace - outline edge: %d is NULL\n",i);
//            continue;
//        }
//        bool addEdge = true;
//        //is edge already in faceEdges?  maybe need to use explorer for this for IsSame to work?
//        for (auto& e:faceEdges) {
//            if (e.IsPartner(edge)) {
//                addEdge = false;
//                Base::Console().Message("TRACE - DVS::projectFace - skipping an edge 1\n");
//            }
//        }
//        expl.ReInit();
//        for (; expl.More(); expl.Next()){
//            const TopoDS_Edge& eHard = TopoDS::Edge(expl.Current());
//            if (eHard.IsPartner(edge)) {
//                addEdge = false;
//                Base::Console().Message("TRACE - DVS::projectFace - skipping an edge 2\n");
//            }
//        }
//        if (addEdge) {
//            faceEdges.push_back(edge);
//        }
//    }

    TopoDS_Face projectedFace;

    if (faceEdges.empty()) {
        Base::Console().Log("LOG - DVS::projectFace - no faceEdges\n");
        return projectedFace;
    }


//recreate the wires for this single face
    EdgeWalker ew;
    ew.loadEdges(faceEdges);
    bool success = ew.perform();
    if (success) {
        std::vector<TopoDS_Wire> fw = ew.getResultNoDups();

        if (!fw.empty()) {
            std::vector<TopoDS_Wire> sortedWires = ew.sortStrip(fw, true);
            if (sortedWires.empty()) {
                return projectedFace;
            }

            BRepBuilderAPI_MakeFace mkFace(sortedWires.front(),true);                   //true => only want planes?
            std::vector<TopoDS_Wire>::iterator itWire = ++sortedWires.begin();          //starting with second face
            for (; itWire != sortedWires.end(); itWire++) {
                mkFace.Add(*itWire);
            }
            projectedFace = mkFace.Face();
        }
    } else {
        Base::Console().Warning("DVS::projectFace - input is not planar graph. No face detection\n");
    }
    return projectedFace;
}
コード例 #24
0
ファイル: math_utils.cpp プロジェクト: fougue/fougtools
gp_Pnt MathUtils::projectPointOnPlane(const gp_Pnt &p, const gp_Vec &n)
{
    const gp_Vec pVec(p.X(), p.Y(), p.Z());
    const Standard_Real dotVN = pVec.Dot(n);
    return p.Translated(-dotVN * n);
}
コード例 #25
0
ファイル: GEOMUtils.cpp プロジェクト: AjinkyaDahale/FreeCAD
//=======================================================================
//function : PreciseBoundingBox
//purpose  : 
//=======================================================================
Standard_Boolean GEOMUtils::PreciseBoundingBox
                          (const TopoDS_Shape &theShape, Bnd_Box &theBox)
{
  if ( theBox.IsVoid() ) BRepBndLib::Add( theShape, theBox );
  if ( theBox.IsVoid() ) return Standard_False;

  Standard_Real aBound[6];
  theBox.Get(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);

  Standard_Integer i;
  const gp_Pnt aMid(0.5*(aBound[1] + aBound[0]),  // XMid
                    0.5*(aBound[3] + aBound[2]),  // YMid
                    0.5*(aBound[5] + aBound[4])); // ZMid
  const gp_XYZ aSize(aBound[1] - aBound[0],       // DX
                     aBound[3] - aBound[2],       // DY
                     aBound[5] - aBound[4]);      // DZ
  const gp_Pnt aPnt[6] =
    {
      gp_Pnt(aBound[0] - (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMin
      gp_Pnt(aBound[1] + (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMax
      gp_Pnt(aMid.X(), aBound[2] - (aBound[3] - aBound[2]), aMid.Z()), // YMin
      gp_Pnt(aMid.X(), aBound[3] + (aBound[3] - aBound[2]), aMid.Z()), // YMax
      gp_Pnt(aMid.X(), aMid.Y(), aBound[4] - (aBound[5] - aBound[4])), // ZMin
      gp_Pnt(aMid.X(), aMid.Y(), aBound[5] + (aBound[5] - aBound[4]))  // ZMax
    };
  const gp_Dir aDir[3] = { gp::DX(), gp::DY(), gp::DZ() };
  const Standard_Real aPlnSize[3] =
    {
      0.5*Max(aSize.Y(), aSize.Z()), // XMin, XMax planes
      0.5*Max(aSize.X(), aSize.Z()), // YMin, YMax planes
      0.5*Max(aSize.X(), aSize.Y())  // ZMin, ZMax planes
    };
  gp_Pnt aPMin[2];

  for (i = 0; i < 6; i++) {
    const Standard_Integer iHalf = i/2;
    const gp_Pln aPln(aPnt[i], aDir[iHalf]);
    BRepBuilderAPI_MakeFace aMkFace(aPln, -aPlnSize[iHalf], aPlnSize[iHalf],
                                    -aPlnSize[iHalf], aPlnSize[iHalf]);

    if (!aMkFace.IsDone()) {
      return Standard_False;
    }

    TopoDS_Shape aFace = aMkFace.Shape();

    // Get minimal distance between planar face and shape.
    Standard_Real aMinDist =
      GEOMUtils::GetMinDistance(aFace, theShape, aPMin[0], aPMin[1]);

    if (aMinDist < 0.) {
      return Standard_False;
    }

    aBound[i] = aPMin[1].Coord(iHalf + 1);
  }

  // Update Bounding box with the new values.
  theBox.SetVoid();
  theBox.Update(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);

  return Standard_True;
}
コード例 #26
0
//=======================================================================
//function : HasIntersection3
//purpose  : Auxilare for HasIntersection()
//           find intersection point between triangle (P1,P2,P3)
//           and segment [PC,P]
//=======================================================================
static bool HasIntersection3(const gp_Pnt& P, const gp_Pnt& PC, gp_Pnt& Pint,
                             const gp_Pnt& P1, const gp_Pnt& P2, const gp_Pnt& P3)
{
  //cout<<"HasIntersection3"<<endl;
  //cout<<"  PC("<<PC.X()<<","<<PC.Y()<<","<<PC.Z()<<")"<<endl;
  //cout<<"  P("<<P.X()<<","<<P.Y()<<","<<P.Z()<<")"<<endl;
  //cout<<"  P1("<<P1.X()<<","<<P1.Y()<<","<<P1.Z()<<")"<<endl;
  //cout<<"  P2("<<P2.X()<<","<<P2.Y()<<","<<P2.Z()<<")"<<endl;
  //cout<<"  P3("<<P3.X()<<","<<P3.Y()<<","<<P3.Z()<<")"<<endl;
  gp_Vec VP1(P1,P2);
  gp_Vec VP2(P1,P3);
  IntAna_Quadric IAQ(gp_Pln(P1,VP1.Crossed(VP2)));
  IntAna_IntConicQuad IAICQ(gp_Lin(PC,gp_Dir(gp_Vec(PC,P))),IAQ);
  if(IAICQ.IsDone()) {
    if( IAICQ.IsInQuadric() )
      return false;
    if( IAICQ.NbPoints() == 1 ) {
      gp_Pnt PIn = IAICQ.Point(1);
      double preci = 1.e-6;
      // check if this point is internal for segment [PC,P]
      bool IsExternal =
        ( (PC.X()-PIn.X())*(P.X()-PIn.X()) > preci ) ||
        ( (PC.Y()-PIn.Y())*(P.Y()-PIn.Y()) > preci ) ||
        ( (PC.Z()-PIn.Z())*(P.Z()-PIn.Z()) > preci );
      if(IsExternal) {
        return false;
      }
      // check if this point is internal for triangle (P1,P2,P3)
      gp_Vec V1(PIn,P1);
      gp_Vec V2(PIn,P2);
      gp_Vec V3(PIn,P3);
      if( V1.Magnitude()<preci || V2.Magnitude()<preci ||
          V3.Magnitude()<preci ) {
        Pint = PIn;
        return true;
      }
      gp_Vec VC1 = V1.Crossed(V2);
      gp_Vec VC2 = V2.Crossed(V3);
      gp_Vec VC3 = V3.Crossed(V1);
      if(VC1.Magnitude()<preci) {
        if(VC2.IsOpposite(VC3,preci)) {
          return false;
        }
      }
      else if(VC2.Magnitude()<preci) {
        if(VC1.IsOpposite(VC3,preci)) {
          return false;
        }
      }
      else if(VC3.Magnitude()<preci) {
        if(VC1.IsOpposite(VC2,preci)) {
          return false;
        }
      }
      else {
        if( VC1.IsOpposite(VC2,preci) || VC1.IsOpposite(VC3,preci) ||
            VC2.IsOpposite(VC3,preci) ) {
          return false;
        }
      }
      Pint = PIn;
      return true;
    }
  }

  return false;
}
コード例 #27
0
ファイル: Excellon.cpp プロジェクト: DesignerMK/heekscnc
bool Excellon::ReadDataBlock( const std::string & data_block )
{
	std::string _data( data_block );
	std::string::size_type offset;
	while ((offset = _data.find('%')) != _data.npos) _data.erase(offset,1);
	while ((offset = _data.find('*')) != _data.npos) _data.erase(offset,1);
	while ((offset = _data.find(',')) != _data.npos) _data.erase(offset,1);
	while ((offset = _data.find(' ')) != _data.npos) _data.erase(offset,1);
	while ((offset = _data.find('\t')) != _data.npos) _data.erase(offset,1);
	while ((offset = _data.find('\r')) != _data.npos) _data.erase(offset,1);

	char buffer[1024];
	memset(buffer,'\0', sizeof(buffer));
	strcpy( buffer, data_block.c_str() );

	static gp_Pnt position(0.0,0.0,0.0);
	bool position_has_been_set = false;

	bool m02_found = false;
	bool swap_axis = false;
	bool mirror_image_x_axis = false;
	bool mirror_image_y_axis = false;
	unsigned int excellon_tool_number = 0;
	double tool_diameter = 0.0;

	while (_data.size() > 0)
	{
	    if (_data.substr(0,2) == "RT")
		{
			// Reset Tool Data
			_data.erase(0,2);
            m_tool_table_map.clear();
            m_active_tool_number = 0;
		}
		else if (_data.substr(0,4) == "FMAT")
		{
			// Ignore format
			_data.erase(0,4);
			char *end = NULL;
			unsigned long format = strtoul( _data.c_str(), &end, 10 );
			_data.erase(0, end - _data.c_str());
			printf("Ignoring Format %ld command\n", format );
		}
		else if (_data.substr(0,3) == "AFS")
		{
			// Ignore format
			_data.erase(0,3);
			printf("Ignoring Automatic Feeds and Speeds\n");
		}
		else if (_data.substr(0,3) == "CCW")
		{
			_data.erase(0,3);
			printf("Ignoring Counter-Clockwise routing\n");
		}
		else if (_data.substr(0,2) == "CP")
		{
			_data.erase(0,2);
			printf("Ignoring Cutter Compensation\n");
		}
		else if (_data.substr(0,6) == "DETECT")
		{
			_data.erase(0,6);
			printf("Ignoring Broken Tool Detection\n");
		}
        else if (_data.substr(0,2) == "DN")
		{
			_data.erase(0,2);
			printf("Ignoring Down Limit Set\n");
		}
		else if (_data.substr(0,6) == "DTMDIST")
		{
			_data.erase(0,6);
			printf("Ignoring Maximum Route Distance Before Tool Change\n");
		}
		else if (_data.substr(0,4) == "EXDA")
		{
			_data.erase(0,4);
			printf("Ignoring Extended Drill Area\n");
		}
		else if (_data.substr(0,3) == "FSB")
		{
			_data.erase(0,3);
			printf("Ignoring Feeds and Speeds Button OFF\n");
		}
		else if (_data.substr(0,4) == "HBCK")
		{
			_data.erase(0,4);
			printf("Ignoring Home Button Check\n");
		}
		else if (_data.substr(0,4) == "NCSL")
		{
			_data.erase(0,4);
			printf("Ignoring NC Slope Enable/Disable\n");
		}
		else if (_data.substr(0,4) == "OM48")
		{
			_data.erase(0,4);
			printf("Ignoring Override Part Program Header\n");
		}
		else if (_data.substr(0,5) == "OSTOP")
		{
			_data.erase(0,5);
			printf("Ignoring Optional Stop switch\n");
		}
		else if (_data.substr(0,6) == "OTCLMP")
		{
			_data.erase(0,6);
			printf("Ignoring Override Table Clamp\n");
		}
		else if (_data.substr(0,8) == "PCKPARAM")
		{
			_data.erase(0,8);
			printf("Ignoring Set up pecking tool,depth,infeed and retract parameters\n");
		}
        else if (_data.substr(0,2) == "PF")
		{
			_data.erase(0,2);
			printf("Ignoring Floating Pressure Foot Switch\n");
		}
		else if (_data.substr(0,3) == "PPR")
		{
			_data.erase(0,3);
			printf("Ignoring Programmable Plunge Rate Enable\n");
		}
		else if (_data.substr(0,3) == "PVS")
		{
			_data.erase(0,3);
			printf("Ignoring Pre-vacuum Shut-off Switch\n");
		}
		else if (_data.substr(0,3) == "RC")
		{
			_data.erase(0,3);
			printf("Ignoring Reset Clocks\n");
		}
		else if (_data.substr(0,3) == "RCP")
		{
			_data.erase(0,3);
			printf("Ignoring Reset Program Clocks\n");
		}
		else if (_data.substr(0,3) == "RCR")
		{
			_data.erase(0,3);
			printf("Ignoring Reset Run Clocks\n");
		}
		else if (_data.substr(0,2) == "RD")
		{
			_data.erase(0,2);
			printf("Ignoring Reset All Cutter Distances\n");
		}
		else if (_data.substr(0,2) == "RH")
		{
			_data.erase(0,2);
			printf("Ignoring Reset All Hit Counters\n");
		}
		else if (_data.substr(0,3) == "SBK")
		{
			_data.erase(0,3);
			printf("Ignoring Single Block Mode Switch\n");
		}
		else if (_data.substr(0,2) == "SG")
		{
			_data.erase(0,2);
			printf("Ignoring Spindle Group Mode\n");
		}
		else if (_data.substr(0,4) == "SIXM")
		{
			_data.erase(0,4);
			printf("Ignoring Input From External Source\n");
		}
		else if (_data.substr(0,2) == "UP")
		{
			_data.erase(0,2);
			printf("Ignoring Upper Limit Switch Set\n");
		}
		else if (_data.substr(0,2) == "ZA")
		{
			_data.erase(0,2);
			printf("Ignoring Auxiliary Zero\n");
		}
		else if (_data.substr(0,2) == "ZC")
		{
			_data.erase(0,2);
			printf("Ignoring Zero Correction\n");
		}
		else if (_data.substr(0,2) == "ZS")
		{
			_data.erase(0,2);
			printf("Ignoring Zero Preset\n");
		}
		else if (_data.substr(0,1) == "Z")
		{
			_data.erase(0,1);
			printf("Ignoring Zero Set\n");
		}
		else if (_data.substr(0,3) == "VER")
		{
			// Ignore version
			_data.erase(0,3);
			char *end = NULL;
			unsigned long version = strtoul( _data.c_str(), &end, 10 );
			_data.erase(0, end - _data.c_str());
			printf("Ignoring Version %ld command\n", version);
		}
		else if (_data.substr(0,6) == "TCSTON")
		{
			// Tool Change Stop - ON
			printf("Ignoring Tool Change Stop - ON command\n");
			_data.erase(0,6);
		}
		else if (_data.substr(0,7) == "TCSTOFF")
		{
			// Tool Change Stop - OFF
			printf("Ignoring Tool Change Stop - OFF command\n");
			_data.erase(0,7);
		}
		else if (_data.substr(0,5) == "ATCON")
		{
			// Automatic Tool Change - ON
			printf("Ignoring Tool Change - ON command\n");
			_data.erase(0,5);
		}
		else if (_data.substr(0,6) == "ATCOFF")
		{
			// Automatic Tool Change - OFF
			printf("Ignoring Tool Change - OFF command\n");
			_data.erase(0,6);
		}
		else if (_data.substr(0,3) == "M30")
		{
			// End of program
			_data.erase(0,3);
		}
		else if (_data.substr(0,1) == ";")
		{
			_data.erase(0,1);
			return(true);	// Ignore all subsequent comments until the end of line.
		}
		else if (_data.substr(0,4) == "INCH")
		{
			_data.erase(0,4);
			m_units = 25.4;	// Imperial
		}
		else if (_data.substr(0,6) == "METRIC")
		{
			_data.erase(0,6);
			m_units = 1.0;	// mm
		}
		else if (_data.substr(0,2) == "MM")
		{
			_data.erase(0,2);
			m_units = 1.0;	// mm
		}
		else if (_data.substr(0,2) == "TZ")
		{
			_data.erase(0,2);
			// In Excellon files, the TZ means that trailing zeroes are INCLUDED
			// while in RS274X format, it means they're OMITTED
			m_trailingZeroSuppression = false;
		}
		else if (_data.substr(0,2) == "LZ")
		{
			_data.erase(0,2);
			// In Excellon files, the LZ means that leading zeroes are INCLUDED
			// while in RS274X format, it means they're OMITTED
			m_leadingZeroSuppression = false;
		}
		else if (_data.substr(0,1) == "T")
		{
			_data.erase(0,1);
			char *end = NULL;
			excellon_tool_number = strtoul( _data.c_str(), &end, 10 );
			_data.erase(0, end - _data.c_str());
		}
		else if (_data.substr(0,1) == "C")
		{
			_data.erase(0,1);
			const char *end = NULL;
			tool_diameter = special_strtod( _data.c_str(), &end );
			_data.erase(0, end - _data.c_str());
		}
		else if (_data.substr(0,3) == "M02")
		{
			_data.erase(0,3);
			m02_found = true;
		}
		else if (_data.substr(0,3) == "M00")
		{
			// End of program
			_data.erase(0,3);
		}
		else if ((_data.substr(0,3) == "M25") ||
			 (_data.substr(0,3) == "M31") ||
			 (_data.substr(0,3) == "M08") ||
			 (_data.substr(0,3) == "M01"))
		{
			// Beginning of pattern
			printf("Pattern repetition is not yet supported\n");
			return(false);
		}
		else if (_data.substr(0,1) == "R")
		{
			_data.erase(0,1);
			printf("Pattern repetition is not yet supported\n");
			return(false);

			/*
			char *end = NULL;
			repetitions = strtoul( _data.c_str(), &end, 10 );
			_data.erase(0, end - _data.c_str());
			*/
		}
		else if (_data.substr(0,3) == "M70")
		{
			_data.erase(0,3);
			swap_axis = true;
		}
		else if (_data.substr(0,3) == "M80")
		{
			_data.erase(0,3);
			mirror_image_x_axis = true;
		}
		else if (_data.substr(0,3) == "G90")
		{
			_data.erase(0,3);
			mirror_image_y_axis = true;
		}
		else if (_data.substr(0,1) == "N")
		{
			// Ignore block numbers
			_data.erase(0,1);
			char *end = NULL;
			strtoul( _data.c_str(), &end, 10 );
			_data.erase( 0, end - _data.c_str() );
		}
		else if (_data.substr(0,1) == "X")
		{
			_data.erase(0,1);	// Erase X
			const char *end = NULL;

			double x = special_strtod( _data.c_str(), &end );
			if ((end == NULL) || (end == _data.c_str()))
			{
				printf("Expected number following 'X'\n");
				return(false);
			} // End if - then
			std::string x_string = _data.substr(0, end - _data.c_str());
			_data.erase(0, end - _data.c_str());

            position_has_been_set = true;
            if (x_string.find('.') == std::string::npos)
            {

                double x = InterpretCoord( x_string.c_str(),
                                m_YDigitsLeftOfPoint,
                                m_YDigitsRightOfPoint,
                                m_leadingZeroSuppression,
                                m_trailingZeroSuppression );

                if (m_absoluteCoordinatesMode)
                {
                    position.SetX( x );
                }
                else
                {
                    // Incremental position.
                    position.SetX( position.X() + x );
                }
            }
            else
            {
                // The number had a decimal point explicitly defined within it.  Read it as a correctly
                // represented number as is.
                if (m_absoluteCoordinatesMode)
                {
                    position.SetX( x );
                }
                else
                {
                    // Incremental position.
                    position.SetX( position.X() + x );
                }
            }
		}
		else if (_data.substr(0,1) == "Y")
		{
			_data.erase(0,1);	// Erase Y
			const char *end = NULL;

			double y = special_strtod( _data.c_str(), &end );
			if ((end == NULL) || (end == _data.c_str()))
			{
				printf("Expected number following 'Y'\n");
				return(false);
			} // End if - then
			std::string y_string = _data.substr(0, end - _data.c_str());
			_data.erase(0, end - _data.c_str());

            position_has_been_set = true;
            if (y_string.find('.') == std::string::npos)
            {
                double y = InterpretCoord( y_string.c_str(),
                                m_YDigitsLeftOfPoint,
                                m_YDigitsRightOfPoint,
                                m_leadingZeroSuppression,
                                m_trailingZeroSuppression );

                if (m_absoluteCoordinatesMode)
                {
                    position.SetY( y );
                }
                else
                {
                    // Incremental position.
                    position.SetY( position.Y() + y );
                }
            }
            else
            {
                    // The number already has a decimal point explicitly defined within it.

                    if (m_absoluteCoordinatesMode)
                    {
                        position.SetY( y );
                    }
                    else
                    {
                        // Incremental position.
                        position.SetY( position.Y() + y );
                    }
            }
		}
		else if (_data.substr(0,3) == "G05")
		{
			_data.erase(0,3);
			printf("Ignoring select drill mode (G05) command\n");
		}
		else if (_data.substr(0,3) == "G81")
		{
			_data.erase(0,3);
			printf("Ignoring select drill mode (G81) command\n");
		}
		else if (_data.substr(0,3) == "G04")
		{
			_data.erase(0,3);
			printf("Ignoring variable dwell (G04) command\n");
		}
		else if (_data.substr(0,3) == "G90")
		{
			_data.erase(0,3);
			m_absoluteCoordinatesMode = true; 	// It's the only mode we use anyway.
		}
        else if (_data.substr(0,6) == "ICIOFF")
		{
			_data.erase(0,6);
			m_absoluteCoordinatesMode = true; 	// It's the only mode we use anyway.
		}
		else if (_data.substr(0,3) == "G91")    // Incremental coordinates mode ON
		{
			_data.erase(0,3);
			m_absoluteCoordinatesMode = false;
		}
		else if (_data.substr(0,5) == "ICION")    // Incremental coordinates mode ON
		{
			_data.erase(0,5);
			m_absoluteCoordinatesMode = false;
		}
		else if (_data.substr(0,3) == "G92")
		{
			_data.erase(0,3);
			printf("Set zero (G92) is not yet supported\n");
			return(false);
		}
		else if (_data.substr(0,3) == "G93")
		{
			_data.erase(0,3);
			printf("Set zero (G93) is not yet supported\n");
			return(false);
		}
		else if (_data.substr(0,3) == "M48")
		{
			_data.erase(0,3);
			// Ignore 'Program Header to first "%"'
		}
		else if (_data.substr(0,3) == "M47")
		{
			_data.erase(0,3);
			// Ignore 'Operator Message CRT Display'
			return(true);	// Ignore the rest of the line.
		}
		else if (_data.substr(0,3) == "M71")
		{
			_data.erase(0,3);
			m_units = 1.0;	// Metric
		}
		else if (_data.substr(0,3) == "M72")
		{
			_data.erase(0,3);
			m_units = 25.4;	// Imperial
		}
		else if (_data.substr(0,1) == "S")
		{
			_data.erase(0,1);
			const char *end = NULL;
			m_spindle_speed = special_strtod( _data.c_str(), &end );
			_data.erase(0, end - _data.c_str());
		}
		else if (_data.substr(0,1) == "F")
		{
			_data.erase(0,1);
			const char *end = NULL;
			m_feed_rate = special_strtod( _data.c_str(), &end ) * m_units;
			_data.erase(0, end - _data.c_str());
		}
		else
		{
			printf("Unexpected command '%s'\n", _data.c_str() );
			return(false);
		} // End if - else
	} // End while

    if (excellon_tool_number > 0)
	{
		// We either want to find an existing drill bit of this size or we need
		// to define a new one.

		if ((tool_diameter <= 0.0) && s_allow_dummy_tool_definitions)
		{
			// The file doesn't define the tool's diameter.  Just convert the tool number into a value in thousanths
			// of an inch and let it through.

			tool_diameter = (excellon_tool_number * 0.001);
		}

		bool found = false;
		for (HeeksObj *tool = theApp.m_program->Tools()->GetFirstChild(); tool != NULL; tool = theApp.m_program->Tools()->GetNextChild() )
		{
			// We're looking for a tool whose diameter is tool_diameter.
			CTool *pTool = (CTool *)tool;
			if (fabs(pTool->m_params.m_diameter - tool_diameter) < heeksCAD->GetTolerance())
			{
				// We've found it.
				// Keep a map of the tool numbers found in the Excellon file to those in our tool table.
				m_tool_table_map.insert( std::make_pair( excellon_tool_number, pTool->m_tool_number ));
				m_active_tool_number = pTool->m_tool_number;	// Use our internal tool number
				found = true;
				break;
			} // End if - then
		} // End for

        if ((! found) && (tool_diameter > 0.0))
        {
            // We didn't find an existing tool with the right diameter.  Add one now.
            int id = heeksCAD->GetNextID(ToolType);
            CTool *tool = new CTool(NULL, CToolParams::eDrill, id);
            heeksCAD->SetObjectID( tool, id );
            tool->SetDiameter( tool_diameter * m_units );
            theApp.m_program->Tools()->Add( tool, NULL );

            // Keep a map of the tool numbers found in the Excellon file to those in our tool table.
            m_tool_table_map.insert( std::make_pair( excellon_tool_number, tool->m_tool_number ));
            m_active_tool_number = tool->m_tool_number;	// Use our internal tool number
        }
	} // End if - then

	if (excellon_tool_number > 0)
	{
		// They may have selected a tool.
		m_active_tool_number = m_tool_table_map[excellon_tool_number];
	} // End if - then


	if (position_has_been_set)
	{
		if (m_active_tool_number <= 0)
		{
			printf("Hole position defined without selecting a tool first\n");
			return(false);
		} // End if - then
		else
		{
			// We've been given a position.  See if we already have a point object
			// at this location.  If so, use it.  Otherwise add a new one.
			CNCPoint cnc_point( position );
			if (m_mirror_image_x_axis) cnc_point.SetY( cnc_point.Y() * -1.0 ); // mirror about X axis
            if (m_mirror_image_y_axis) cnc_point.SetX( cnc_point.X() * -1.0 ); // mirror about Y axis

			if (m_existing_points.find( cnc_point ) == m_existing_points.end())
			{
				// There are no pre-existing Point objects for this location.  Add one now.
				double location[3];
				cnc_point.ToDoubleArray( location );
				HeeksObj *point = heeksCAD->NewPoint( location );
				heeksCAD->Add( point, NULL );
				CDrilling::Symbol_t symbol( point->GetType(), point->m_id );
				m_existing_points.insert( std::make_pair( cnc_point, symbol ));
			} // End if - then

			// There is already a point here.  Use it.
			if (m_holes.find( m_active_tool_number ) == m_holes.end())
			{
				// We haven't used this drill bit before.  Add it now.
				CDrilling::Symbols_t symbols;
				CDrilling::Symbol_t symbol( m_existing_points[ cnc_point ] );
				symbols.push_back( symbol );

				m_holes.insert( std::make_pair( m_active_tool_number, symbols ) );
			}
			else
			{
				// We've already used this drill bit.  Just add to its list of symbols.
				m_holes[ m_active_tool_number ].push_back( m_existing_points[ cnc_point ] );
			} // End if - else

			/*
			printf("Drill hole using tool %d at x=%lf, y=%lf z=%lf\n", m_active_tool_number,
				pPosition->X(), pPosition->Y(), pPosition->Z() );
			*/
		} // End if - else
	} // End if - then



	return(true);
} // End ReadDataBlock() method
コード例 #28
0
ファイル: HDimension.cpp プロジェクト: CarlosGS/heekscad
// static
void HDimension::draw_arrow_line(DimensionMode mode, const gp_Pnt &p0, const gp_Pnt &p1, const gp_Pnt &p2, const gp_Dir &xdir, const gp_Dir &ydir, double width, double scale)
{
	double short_line_length = 5.0 * scale;
	double long_line_extra = 2.0 * scale;

	double y0 = gp_Vec(p2.XYZ()) * gp_Vec(ydir.XYZ()) - gp_Vec(p0.XYZ()) * gp_Vec(ydir.XYZ());
	double y1 = gp_Vec(p2.XYZ()) * gp_Vec(ydir.XYZ()) - gp_Vec(p1.XYZ()) * gp_Vec(ydir.XYZ());

	gp_Pnt vt0( p0.XYZ() + ydir.XYZ() * y0);
	gp_Pnt vt1( p1.XYZ() + ydir.XYZ() * y1);
	gp_Pnt vt2 = p2;

	gp_Dir along_dir = make_vector(gp_Pnt(p0), gp_Pnt(p1));
	gp_Dir xdir_along = xdir;
	if(along_dir * xdir < 0)xdir_along = -xdir;

	gp_Pnt new_vt0 = vt0;
	gp_Pnt new_vt1 = vt1;

	gp_Pnt middle_text_point = p2.XYZ() + along_dir.XYZ() * (width/2 * scale);
	double x0 = gp_Vec(p0.XYZ()) * gp_Vec(xdir_along.XYZ());
	double x1 = gp_Vec(p1.XYZ()) * gp_Vec(xdir_along.XYZ());
	double xm = gp_Vec(middle_text_point.XYZ()) * gp_Vec(xdir_along.XYZ());

	double arrow_head_scale = scale;
	if(xm < x0 || xm > x1)
	{
		arrow_head_scale *= -1;
	}

	double distance = vt0.Distance(vt1);

	// draw arrow heads, if there's room
	if((distance > 2 * scale + wxGetApp().m_geom_tol) || (xm < x0) || (xm > x1))
	{
		gp_XYZ t[2][3];
		t[0][0] = vt0.XYZ();
		t[0][1] = vt0.XYZ() + xdir_along.XYZ() * arrow_head_scale + ydir.XYZ() * (arrow_head_scale * (-0.4));
		t[0][2] = vt0.XYZ() + xdir_along.XYZ() * arrow_head_scale + ydir.XYZ() * (arrow_head_scale * 0.4);
		t[1][0] = vt1.XYZ();
		t[1][1] = vt1.XYZ() + xdir_along.XYZ() * (-arrow_head_scale) + ydir.XYZ() * (arrow_head_scale * 0.4);
		t[1][2] = vt1.XYZ() + xdir_along.XYZ() * (-arrow_head_scale) + ydir.XYZ() * (arrow_head_scale * (-0.4));

		// adjust line vertices
		new_vt0 = gp_Pnt(vt0.XYZ() + xdir_along.XYZ() * arrow_head_scale);
		new_vt1 = gp_Pnt(vt1.XYZ() + xdir_along.XYZ() * (-arrow_head_scale));

		// draw two triangles
		for(int i = 0; i<2; i++)
		{
			glBegin(GL_LINE_STRIP);
			glVertex3d(t[i][0].X(), t[i][0].Y(), t[i][0].Z());
			glVertex3d(t[i][1].X(), t[i][1].Y(), t[i][1].Z());
			glVertex3d(t[i][2].X(), t[i][2].Y(), t[i][2].Z());
			glVertex3d(t[i][0].X(), t[i][0].Y(), t[i][0].Z());
			glEnd();
		}
	}

	// draw side lines
	glBegin(GL_LINES);
	glVertex3d(p0.X(), p0.Y(), p0.Z());
	glVertex3d(vt0.X(), vt0.Y(), vt0.Z());
	glVertex3d(p1.X(), p1.Y(), p1.Z());
	glVertex3d(vt1.X(), vt1.Y(), vt1.Z());
	glEnd();

	if(xm < x0)
	{
		// long line first
		gp_Pnt vt4 = vt2.XYZ() + xdir_along.XYZ() * (-long_line_extra);
		glBegin(GL_LINES);
		glVertex3d(vt2.X(), vt2.Y(), vt2.Z());
		glVertex3d(new_vt0.X(), new_vt0.Y(), new_vt0.Z());
		glEnd();

		// little line
		gp_Pnt vt3 = new_vt1.XYZ() + xdir_along.XYZ() * short_line_length;
		glBegin(GL_LINES);
		glVertex3d(new_vt1.X(), new_vt1.Y(), new_vt1.Z());
		glVertex3d(vt3.X(), vt3.Y(), vt3.Z());
		glEnd();
	}
	else if(xm > x1)
	{
		// little first
		gp_Pnt vt3 = new_vt0.XYZ() - xdir_along.XYZ() * short_line_length;
		glBegin(GL_LINES);
		glVertex3d(vt3.X(), vt3.Y(), vt3.Z());
		glVertex3d(new_vt0.X(), new_vt0.Y(), new_vt0.Z());
		glEnd();

		// long line
		glBegin(GL_LINES);
		gp_Pnt vt4 = vt2.XYZ() + xdir_along.XYZ() * (width * scale + long_line_extra);
		glVertex3d(vt1.X(), vt1.Y(), vt1.Z());
		glVertex3d(vt4.X(), vt4.Y(), vt4.Z());
		glEnd();
	}
	else
	{
		// draw the arrow line
		glBegin(GL_LINES);
		glVertex3d(new_vt0.X(), new_vt0.Y(), new_vt0.Z());
		glVertex3d(new_vt1.X(), new_vt1.Y(), new_vt1.Z());
		glEnd();
	}
}