//this routine is the big time consumer.  gets called many times (and is slow?))
//note param gets modified here
bool DrawProjectSplit::isOnEdge(TopoDS_Edge e, TopoDS_Vertex v, double& param, bool allowEnds)
{
    bool result = false;
    bool outOfBox = false;
    param = -2;

    //eliminate obvious cases
    Bnd_Box sBox;
    BRepBndLib::Add(e, sBox);
    sBox.SetGap(0.1);
    if (sBox.IsVoid()) {
        Base::Console().Message("DPS::isOnEdge - Bnd_Box is void\n");
    } else {
        gp_Pnt pt = BRep_Tool::Pnt(v);
        if (sBox.IsOut(pt)) {
            outOfBox = true;
        }
    }
    if (!outOfBox) {
            double dist = DrawUtil::simpleMinDist(v,e);
            if (dist < 0.0) {
                Base::Console().Error("DPS::isOnEdge - simpleMinDist failed: %.3f\n",dist);
                result = false;
            } else if (dist < Precision::Confusion()) {
                const gp_Pnt pt = BRep_Tool::Pnt(v);                         //have to duplicate method 3 to get param
                BRepAdaptor_Curve adapt(e);
                const Handle_Geom_Curve c = adapt.Curve().Curve();
                double maxDist = 0.000001;     //magic number.  less than this gives false positives.
                //bool found =
                (void) GeomLib_Tool::Parameter(c,pt,maxDist,param);  //already know point it on curve
                result = true;
            }
            if (result) {
                TopoDS_Vertex v1 = TopExp::FirstVertex(e);
                TopoDS_Vertex v2 = TopExp::LastVertex(e);
                if (DrawUtil::isSamePoint(v,v1) || DrawUtil::isSamePoint(v,v2)) {
                    if (!allowEnds) {
                        result = false;
                    }
                }
            }
    } //!outofbox
    return result;
}
//! get the projected edges with all their new intersections.
std::vector<TopoDS_Edge> DrawProjectSplit::getEdges(TechDrawGeometry::GeometryObject* geometryObject)
{
    const std::vector<TechDrawGeometry::BaseGeom*>& goEdges = geometryObject->getVisibleFaceEdges(true,true);
    std::vector<TechDrawGeometry::BaseGeom*>::const_iterator itEdge = goEdges.begin();
    std::vector<TopoDS_Edge> origEdges;
    for (;itEdge != goEdges.end(); itEdge++) {
        origEdges.push_back((*itEdge)->occEdge);
    }

    std::vector<TopoDS_Edge> faceEdges;
    std::vector<TopoDS_Edge> nonZero;
    for (auto& e:origEdges) {                            //drop any zero edges (shouldn't be any by now!!!)
        if (!DrawUtil::isZeroEdge(e)) {
            nonZero.push_back(e);
        } else {
            Base::Console().Message("INFO - DPS::getEdges found ZeroEdge!\n");
        }
    }
    faceEdges = nonZero;
    origEdges = nonZero;

    //HLR algo does not provide all edge intersections for edge endpoints.
    //need to split long edges touched by Vertex of another edge
    std::vector<splitPoint> splits;
    std::vector<TopoDS_Edge>::iterator itOuter = origEdges.begin();
    int iOuter = 0;
    for (; itOuter != origEdges.end(); ++itOuter, iOuter++) {
        TopoDS_Vertex v1 = TopExp::FirstVertex((*itOuter));
        TopoDS_Vertex v2 = TopExp::LastVertex((*itOuter));
        Bnd_Box sOuter;
        BRepBndLib::Add(*itOuter, sOuter);
        sOuter.SetGap(0.1);
        if (sOuter.IsVoid()) {
            Base::Console().Message("DPS::Extract Faces - outer Bnd_Box is void\n");
            continue;
        }
        if (DrawUtil::isZeroEdge(*itOuter)) {
            Base::Console().Message("DPS::extractFaces - outerEdge: %d is ZeroEdge\n",iOuter);   //this is not finding ZeroEdges
            continue;  //skip zero length edges. shouldn't happen ;)
        }
        int iInner = 0;
        std::vector<TopoDS_Edge>::iterator itInner = faceEdges.begin();
        for (; itInner != faceEdges.end(); ++itInner,iInner++) {
            if (iInner == iOuter) {
                continue;
            }
            if (DrawUtil::isZeroEdge((*itInner))) {
                continue;  //skip zero length edges. shouldn't happen ;)
            }

            Bnd_Box sInner;
            BRepBndLib::Add(*itInner, sInner);
            sInner.SetGap(0.1);
            if (sInner.IsVoid()) {
                Base::Console().Log("INFO - DPS::Extract Faces - inner Bnd_Box is void\n");
                continue;
            }
            if (sOuter.IsOut(sInner)) {      //bboxes of edges don't intersect, don't bother
                continue;
            }

            double param = -1;
            if (isOnEdge((*itInner),v1,param,false)) {
                gp_Pnt pnt1 = BRep_Tool::Pnt(v1);
                splitPoint s1;
                s1.i = iInner;
                s1.v = Base::Vector3d(pnt1.X(),pnt1.Y(),pnt1.Z());
                s1.param = param;
                splits.push_back(s1);
            }
            if (isOnEdge((*itInner),v2,param,false)) {
                gp_Pnt pnt2 = BRep_Tool::Pnt(v2);
                splitPoint s2;
                s2.i = iInner;
                s2.v = Base::Vector3d(pnt2.X(),pnt2.Y(),pnt2.Z());
                s2.param = param;
                splits.push_back(s2);
            }
        } //inner loop
    }   //outer loop

    std::vector<splitPoint> sorted = sortSplits(splits,true);
    auto last = std::unique(sorted.begin(), sorted.end(), DrawProjectSplit::splitEqual);  //duplicates to back
    sorted.erase(last, sorted.end());                         //remove dupls
    std::vector<TopoDS_Edge> newEdges = splitEdges(faceEdges,sorted);

    if (newEdges.empty()) {
        Base::Console().Log("LOG - DPS::extractFaces - no newEdges\n");
    }
    newEdges = removeDuplicateEdges(newEdges);
    return newEdges;
}
Example #3
0
//this routine is the big time consumer.  gets called many times (and is slow?))
//note param gets modified here
bool DrawViewPart::isOnEdge(TopoDS_Edge e, TopoDS_Vertex v, double& param, bool allowEnds)
{
    bool result = false;
    bool outOfBox = false;
    param = -2;

    //eliminate obvious cases
    Bnd_Box sBox;
    BRepBndLib::Add(e, sBox);
    sBox.SetGap(0.1);
    if (sBox.IsVoid()) {
        Base::Console().Message("DVP::isOnEdge - Bnd_Box is void for %s\n",getNameInDocument());
    } else {
        gp_Pnt pt = BRep_Tool::Pnt(v);
        if (sBox.IsOut(pt)) {
            outOfBox = true;
        }
    }
    if (!outOfBox) {
        if (m_interAlgo == 1) {
            //1) using projPointOnCurve.  roughly similar to dist to shape w/ bndbox.  hangs(?) w/o bndbox
            try {
                gp_Pnt pt = BRep_Tool::Pnt(v);
                BRepAdaptor_Curve adapt(e);
                Handle_Geom_Curve c = adapt.Curve().Curve();
                GeomAPI_ProjectPointOnCurve proj(pt,c);
                int n = proj.NbPoints();
                if (n > 0) {
                    if (proj.LowerDistance() < Precision::Confusion()) {
                        param = proj.LowerDistanceParameter();
                        result = true;
                    }
                    if (result) {
                        TopoDS_Vertex v1 = TopExp::FirstVertex(e);
                        TopoDS_Vertex v2 = TopExp::LastVertex(e);
                        if (DrawUtil::isSamePoint(v,v1) || DrawUtil::isSamePoint(v,v2)) {
                            if (!allowEnds) {
                                result = false;
                            }
                        }
                    }
                }
            }
            catch (Standard_Failure) {
                Handle_Standard_Failure e = Standard_Failure::Caught();     //no perp projection
            }
        } else if (m_interAlgo == 2) {                                      //can't provide param as is
            double dist = simpleMinDist(v,e);
            if (dist < 0.0) {
                Base::Console().Error("DVP::isOnEdge - simpleMinDist failed: %.3f\n",dist);
                result = false;
            } else if (dist < Precision::Confusion()) {
                const gp_Pnt pt = BRep_Tool::Pnt(v);                         //have to duplicate method 3 to get param
                BRepAdaptor_Curve adapt(e);
                const Handle_Geom_Curve c = adapt.Curve().Curve();
                double maxDist = 0.000001;     //magic number.  less than this gives false positives.
                //bool found =
                (void) GeomLib_Tool::Parameter(c,pt,maxDist,param);  //already know point it on curve
                result = true;
            }
            if (result) {
                TopoDS_Vertex v1 = TopExp::FirstVertex(e);
                TopoDS_Vertex v2 = TopExp::LastVertex(e);
                if (DrawUtil::isSamePoint(v,v1) || DrawUtil::isSamePoint(v,v2)) {
                    if (!allowEnds) {
                        result = false;
                    }
                }
            }
        } else if (m_interAlgo == 3) {
            const gp_Pnt pt = BRep_Tool::Pnt(v);
            BRepAdaptor_Curve adapt(e);
            const Handle_Geom_Curve c = adapt.Curve().Curve();
            double par = -1;
            double maxDist = 0.000001;     //magic number.  less than this gives false positives.
            bool found = GeomLib_Tool::Parameter(c,pt,maxDist,par);
            if (found) {
                result = true;
                param = par;
                TopoDS_Vertex v1 = TopExp::FirstVertex(e);
                TopoDS_Vertex v2 = TopExp::LastVertex(e);
                if (DrawUtil::isSamePoint(v,v1) || DrawUtil::isSamePoint(v,v2)) {
                    if (!allowEnds) {
                        result = false;
                    }
                }
            }
        }
    } //!outofbox
    return result;
}
Example #4
0
//! make faces from the existing edge geometry
void DrawViewPart::extractFaces()
{
    geometryObject->clearFaceGeom();
    const std::vector<TechDrawGeometry::BaseGeom*>& goEdges =
                       geometryObject->getVisibleFaceEdges(SmoothVisible.getValue(),SeamVisible.getValue());
    std::vector<TechDrawGeometry::BaseGeom*>::const_iterator itEdge = goEdges.begin();
    std::vector<TopoDS_Edge> origEdges;
    for (;itEdge != goEdges.end(); itEdge++) {
        origEdges.push_back((*itEdge)->occEdge);
    }


    std::vector<TopoDS_Edge> faceEdges;
    std::vector<TopoDS_Edge> nonZero;
    for (auto& e:origEdges) {                            //drop any zero edges (shouldn't be any by now!!!)
        if (!DrawUtil::isZeroEdge(e)) {
            nonZero.push_back(e);
        } else {
            Base::Console().Message("INFO - DVP::extractFaces for %s found ZeroEdge!\n",getNameInDocument());
        }
    }
    faceEdges = nonZero;
    origEdges = nonZero;

    //HLR algo does not provide all edge intersections for edge endpoints.
    //need to split long edges touched by Vertex of another edge
    std::vector<splitPoint> splits;
    std::vector<TopoDS_Edge>::iterator itOuter = origEdges.begin();
    int iOuter = 0;
    for (; itOuter != origEdges.end(); ++itOuter, iOuter++) {
        TopoDS_Vertex v1 = TopExp::FirstVertex((*itOuter));
        TopoDS_Vertex v2 = TopExp::LastVertex((*itOuter));
        Bnd_Box sOuter;
        BRepBndLib::Add(*itOuter, sOuter);
        sOuter.SetGap(0.1);
        if (sOuter.IsVoid()) {
            Base::Console().Message("DVP::Extract Faces - outer Bnd_Box is void for %s\n",getNameInDocument());
            continue;
        }
        if (DrawUtil::isZeroEdge(*itOuter)) {
            Base::Console().Message("DVP::extractFaces - outerEdge: %d is ZeroEdge\n",iOuter);   //this is not finding ZeroEdges
            continue;  //skip zero length edges. shouldn't happen ;)
        }
        int iInner = 0;
        std::vector<TopoDS_Edge>::iterator itInner = faceEdges.begin();
        for (; itInner != faceEdges.end(); ++itInner,iInner++) {
            if (iInner == iOuter) {
                continue;
            }
            if (DrawUtil::isZeroEdge((*itInner))) {
                continue;  //skip zero length edges. shouldn't happen ;)
            }

            Bnd_Box sInner;
            BRepBndLib::Add(*itInner, sInner);
            sInner.SetGap(0.1);
            if (sInner.IsVoid()) {
                Base::Console().Log("INFO - DVP::Extract Faces - inner Bnd_Box is void for %s\n",getNameInDocument());
                continue;
            }
            if (sOuter.IsOut(sInner)) {      //bboxes of edges don't intersect, don't bother
                continue;
            }

            double param = -1;
            if (DrawProjectSplit::isOnEdge((*itInner),v1,param,false)) {
                gp_Pnt pnt1 = BRep_Tool::Pnt(v1);
                splitPoint s1;
                s1.i = iInner;
                s1.v = Base::Vector3d(pnt1.X(),pnt1.Y(),pnt1.Z());
                s1.param = param;
                splits.push_back(s1);
            }
            if (DrawProjectSplit::isOnEdge((*itInner),v2,param,false)) {
                gp_Pnt pnt2 = BRep_Tool::Pnt(v2);
                splitPoint s2;
                s2.i = iInner;
                s2.v = Base::Vector3d(pnt2.X(),pnt2.Y(),pnt2.Z());
                s2.param = param;
                splits.push_back(s2);
            }
        } //inner loop
    }   //outer loop

    std::vector<splitPoint> sorted = DrawProjectSplit::sortSplits(splits,true);
    auto last = std::unique(sorted.begin(), sorted.end(), DrawProjectSplit::splitEqual);  //duplicates to back
    sorted.erase(last, sorted.end());                         //remove dupl splits
    std::vector<TopoDS_Edge> newEdges = DrawProjectSplit::splitEdges(faceEdges,sorted);

    if (newEdges.empty()) {
        Base::Console().Log("LOG - DVP::extractFaces - no newEdges\n");
        return;
    }

    newEdges = DrawProjectSplit::removeDuplicateEdges(newEdges);

//find all the wires in the pile of faceEdges
    EdgeWalker ew;
    ew.loadEdges(newEdges);
    bool success = ew.perform();
    if (!success) {
        Base::Console().Warning("DVP::extractFaces - input is not planar graph. No face detection\n");
        return;
    }
    std::vector<TopoDS_Wire> fw = ew.getResultNoDups();

    std::vector<TopoDS_Wire> sortedWires = ew.sortStrip(fw,true);

    std::vector<TopoDS_Wire>::iterator itWire = sortedWires.begin();
    for (; itWire != sortedWires.end(); itWire++) {
        //version 1: 1 wire/face - no voids in face
        TechDrawGeometry::Face* f = new TechDrawGeometry::Face();
        const TopoDS_Wire& wire = (*itWire);
        TechDrawGeometry::Wire* w = new TechDrawGeometry::Wire(wire);
        f->wires.push_back(w);
        geometryObject->addFaceGeom(f);
    }
}
bool RoomLayoutPillarController::PreRender3D()
{
	auto& imp_ = *ImpUPtr_;

	plane3df plan(0,0,0,0,1,0);
	auto line = GetRenderContextSPtr()->Smgr_->getSceneCollisionManager()->getRayFromScreenCoordinates(imp_.CursorIPos_);
	plan.getIntersectionWithLine(line.start, line.getVector(), imp_.CurrentPos_);
	imp_.CurrentPos_.Y = 0;
	gp_Pnt cursorPnt(imp_.CurrentPos_.X, imp_.CurrentPos_.Y, imp_.CurrentPos_.Z);

	switch (imp_.State_)
	{
	case EPilarState::EPS_SWEEPING:
		{
			if ( GetPickingODL().expired() )
			{
				break;
			}

			auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());

			activePilar->SetSweeping(true);

			if ( imp_.CtrllHolding_ )
			{
				imp_.State_ = EPilarState::EPS_MODIFY_INIT;
				break;
			}

			if ( imp_.LMousePressDown_ )
			{
				auto box = activePilar->GetBaseBndBox();
				auto pos = activePilar->GetTranslation();

				Standard_Real xMin,xMax,yMin,yMax,zMin,zMax;
				box.Get(xMin, yMin, zMin, xMax, yMax, zMax);

				imp_.EventInfo_ = SEventPillarInfo();
				imp_.EventInfo_->XLength_ = static_cast<float>(xMax-xMin);
				imp_.EventInfo_->YLength_ = static_cast<float>(yMax-yMin);
				imp_.EventInfo_->ZLength_ = static_cast<float>(zMax-zMin);
				imp_.EventInfo_->OffsetHeight_ = activePilar->GetOffsetHeight();

				imp_.SavePos_ = imp_.CurrentPos_;
				imp_.State_ = EPilarState::EPS_MOUSEHOLDING;
			}
		}
		break;
	case EPilarState::EPS_MODIFY_INIT:
		{
			auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());
			activePilar->SetSweeping(true);

			if ( !imp_.CtrllHolding_ )
			{
				GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL);
				imp_.State_ = EPilarState::EPS_SWEEPING;
				imp_.CtrllHolding_ = false;
				break;
			}

			auto box = activePilar->GetBaseBndBox();

			Standard_Real xMin,xMax,yMin,yMax,zMin,zMax;
			box.Get(xMin, yMin, zMin, xMax, yMax, zMax);

			auto modifyAlign = 100;

			Bnd_Box smallBox,bigBox;
			smallBox.Update(xMin+modifyAlign < 0 ? xMin+modifyAlign : 0, yMin+modifyAlign < 0 ? yMin+modifyAlign : 0, zMin+modifyAlign < 0 ? zMin+modifyAlign : 0,
				xMax-modifyAlign > 0 ? xMax-modifyAlign : 0, yMax-modifyAlign > 0 ? yMax-modifyAlign : 0, zMax-modifyAlign > 0 ? zMax-modifyAlign : 0);
			bigBox.Update(xMin-modifyAlign, yMin-modifyAlign, zMin-modifyAlign, xMax+modifyAlign, yMax+modifyAlign, zMax+modifyAlign);

			auto relationCursorPnt = cursorPnt.Transformed(activePilar->GetAbsoluteTransform().Inverted());
			relationCursorPnt.SetY(0);

			if ( Standard_True == bigBox.IsOut(relationCursorPnt) )
			{
				GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL);
				imp_.State_ = EPilarState::EPS_SWEEPING;
				imp_.CtrllHolding_ = false;
				break;
			}

			if ( Standard_False == smallBox.IsOut(relationCursorPnt) )
			{
				GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL);
				break;
			}

			gp_Dir cursorDir = gp_Vec(gp::Origin(), relationCursorPnt);
			{
				auto rad = gp::DX().AngleWithRef(cursorDir, gp::DY());
				rad = rad < 0 ? M_PI * 2 + rad : rad;
				auto mod = std::fmod(rad, M_PI_2);
				if ( mod < M_PI_4 )
				{
					rad -= mod;
				}
				else
				{
					rad = rad - mod + M_PI_2;
				}

				cursorDir = gp::DX().Rotated(gp::OY(), rad);

				mod = std::fmod(rad, M_PI);
				if ( mod < Precision::Angular() )
				{
					GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_SIZEWE);
				}
				else
				{
					GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_SIZENS);
				}
			}

			if ( imp_.LMousePressDown_ )
			{
				auto edge = BRepBuilderAPI_MakeEdge(gp_Lin(gp::Origin().Transformed(activePilar->GetAbsoluteTransform()), cursorDir.Transformed(activePilar->GetAbsoluteTransform()))).Edge();
				BRepAdaptor_Curve moveBC(edge);

				GeomAPI_ProjectPointOnCurve ppc(relationCursorPnt.Transformed(activePilar->GetAbsoluteTransform()), moveBC.Curve().Curve());

				imp_.ModifyEdge_ = moveBC;
				imp_.ModifyPar_ = ppc.LowerDistanceParameter();

				imp_.State_ = EPilarState::EPS_MODIFY;
				break;
			}
		}
		break;
	case EPilarState::EPS_MODIFY:
		{
			auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());
			activePilar->SetPicking(true);

			if ( imp_.LMouseLeftUp_ )
			{
				activePilar->UpdateMesh();
				imp_.State_ = EPilarState::EPS_SWEEPING;
				break;
			}

			GeomAPI_ProjectPointOnCurve ppcCur(cursorPnt, imp_.ModifyEdge_.Curve().Curve());

			auto curPar = ppcCur.LowerDistanceParameter();
			if ( std::abs(curPar - imp_.ModifyPar_) < Precision::Confusion() )
			{
				break;
			}

			//偏移的起始点、终点(绝对)
			gp_Pnt fromPnt,toPnt;
			imp_.ModifyEdge_.D0(imp_.ModifyPar_, fromPnt);
			imp_.ModifyEdge_.D0(curPar, toPnt);

			gp_Vec moveOffset(fromPnt, toPnt);
			auto relationMoveOffset = moveOffset.Transformed(activePilar->GetAbsoluteTransform().Inverted());
			auto modifyDir = imp_.ModifyEdge_.Line().Direction().Transformed(activePilar->GetAbsoluteTransform().Inverted());
			auto modifyOffset = relationMoveOffset;
			{
				modifyOffset.SetX(modifyOffset.X() * modifyDir.X());
				modifyOffset.SetY(modifyOffset.Y() * modifyDir.Y());
				modifyOffset.SetZ(modifyOffset.Z() * modifyDir.Z());
			}
			auto curPillarSize = activePilar->GetSize();
			if ( Standard_False == imp_.ModifyEdge_.Line().Direction().IsEqual(gp_Dir(moveOffset), Precision::Angular()) )
			{//防止大小缩成0				
				auto testSize = curPillarSize + modifyOffset.XYZ();

				auto minSize = 100;
				auto alignSize = testSize - gp_XYZ(minSize,minSize,minSize);
				if ( alignSize.X() < Precision::Confusion() || alignSize.Y() < Precision::Confusion() || alignSize.Z() < Precision::Confusion() )
				{
					break;
				}
			}

			Bnd_Box pillarBox;
			auto pillarBoxSize = curPillarSize + modifyOffset.XYZ();
			gp_Trsf pillarTranslation,pillarRotation,pillarTransformation;
			{
				pillarBox.Update(-pillarBoxSize.X()/2, -pillarBoxSize.Y()/2, -pillarBoxSize.Z()/2, pillarBoxSize.X()/2, pillarBoxSize.Y()/2, pillarBoxSize.Z()/2);

				auto translation = activePilar->GetTranslation() + relationMoveOffset.XYZ()/2;
				pillarTranslation.SetTranslationPart(translation);
				pillarRotation.SetRotation(activePilar->GetRotation());
			}
			pillarTransformation = pillarTranslation * pillarRotation;

			auto offsetHeight = activePilar->GetOffsetHeight();

			//新的位置
			gp_Pnt newPnt = gp::Origin().Transformed(pillarTransformation);
			
			//吸附距离
			static auto alignDis = 200.0;

			//当前的吸附物体
			auto alignODLs = activePilar->GetAlignList();
			alignODLs.erase(std::remove_if(alignODLs.begin(), alignODLs.end(), [&pillarBox,&pillarTransformation](const BaseODLSPtr& alignODL)
			{
				if ( !alignODL )
				{
					return true;
				}

				return alignODL->GetBaseBndBox().Distance(pillarBox.Transformed(alignODL->GetAbsoluteTransform().Inverted() * pillarTransformation)) > alignDis;
			}), alignODLs.end());
			activePilar->SetAlignList(BaseODLList());

			std::multimap<double,BaseODLSPtr> disMap;
			for ( auto& curODL : RootODL_.lock()->GetChildrenList() )
			{
				if ( EODLT_PILLAR != curODL->GetType() && EODLT_WALL != curODL->GetType() )
				{
					continue;
				}

				if ( std::find(alignODLs.begin(), alignODLs.end(), curODL) != alignODLs.end() )
				{
					continue;
				}

				if ( EODLT_PILLAR == curODL->GetType() && curODL == activePilar )
				{
					continue;
				}

				auto dis = curODL->GetBaseBndBox().Distance(pillarBox.Transformed(curODL->GetAbsoluteTransform().Inverted() * pillarTransformation));
				if ( dis > alignDis )
				{
					continue;
				}

				disMap.emplace(dis, curODL);
			}

			for ( auto& curODL : disMap )
			{
				alignODLs.push_back(curODL.second);
			}

			for ( auto& curODL : alignODLs )
			{
				auto alignTransformation = curODL->GetAbsoluteTransform();

				//调整柱box的旋转
				auto activeRotationPillarBox = pillarBox;
				{
					gp_Trsf tfsODL;
					tfsODL.SetRotation(alignTransformation.GetRotation());

					activeRotationPillarBox = activeRotationPillarBox.Transformed(tfsODL.Inverted() * pillarRotation);
				}

				Bnd_Box movingBox,alignODLBox;
				{
					auto curBox = curODL->GetBaseBndBox();

					Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax;
					curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax);

					Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax;
					activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax);

					movingBox.Update(xAlignMin+xPillarMin, yAlignMin+yPillarMin, zAlignMin+zPillarMin,
						xAlignMax+xPillarMax, yAlignMax+yPillarMax, zAlignMax+zPillarMax);

					alignODLBox.Update(xAlignMin+xPillarMin-alignDis, yAlignMin+yPillarMin-alignDis, zAlignMin+zPillarMin-alignDis,
						xAlignMax+xPillarMax+alignDis, yAlignMax+yPillarMax+alignDis, zAlignMax+zPillarMax+alignDis);
				}

				auto inODLPnt = newPnt.Transformed(curODL->GetAbsoluteTransform().Inverted());

				if ( Standard_True == alignODLBox.IsOut(inODLPnt) )
				{
					continue;
				}

				//当前被停靠物体的box shape
				Standard_Real xMin,yMin,zMin,xMax,yMax,zMax;
				movingBox.Get(xMin, yMin, zMin, xMax, yMax, zMax);
				auto alignBoxShape = BRepPrimAPI_MakeBox(gp_Pnt(xMin, yMin, zMin), gp_Pnt(xMax, yMax, zMax)).Shape();
				TopExp_Explorer exp(alignBoxShape, TopAbs_SHELL);

				BRepExtrema_DistShapeShape dss(imp_.ModifyEdge_.Edge().Moved(curODL->GetAbsoluteTransform().Inverted()), exp.Current());

				auto needContinue = false;
				std::map<double, gp_Pnt> tmp;
				for ( auto index=1; index<=dss.NbSolution(); ++index )
				{
					if ( dss.SupportTypeShape2(index) == BRepExtrema_IsOnEdge )
					{
						activePilar->AddAlign(curODL);
						needContinue = true;
						break;
					}

					auto pntOnEdge = dss.PointOnShape1(index);
					auto pntOnBox = dss.PointOnShape2(index);

					if ( pntOnEdge.Distance(pntOnBox) > Precision::Confusion() )
					{
						continue;
					}

					tmp.emplace(pntOnEdge.Distance(inODLPnt), pntOnEdge);
				}

				if ( needContinue )
				{
					continue;
				}

				auto foundPnt = tmp.begin()->second.Transformed(curODL->GetAbsoluteTransform());
				if ( foundPnt.Distance(newPnt) < 1)
				{
					activePilar->AddAlign(curODL);
					continue;
				}
				else
				{
					newPnt = foundPnt;
					break;
				}
			}

 			auto finalOffset = gp_Vec(pillarTranslation.TranslationPart(), newPnt);
			auto finalRelationOffset = finalOffset.Transformed(pillarTransformation.Inverted());
			auto finalModifyOffset = finalRelationOffset;
			{
				finalModifyOffset.SetX(finalModifyOffset.X()*modifyDir.X());
				finalModifyOffset.SetY(finalModifyOffset.Y()*modifyDir.Y());
				finalModifyOffset.SetZ(finalModifyOffset.Z()*modifyDir.Z());
			}

			auto finalSize = pillarBoxSize + finalModifyOffset.XYZ();
			auto finalTranslation = pillarTranslation.TranslationPart() + finalRelationOffset.XYZ()/2;

			activePilar->SetSize(finalSize);
			activePilar->SetTranslation(finalTranslation);
			{
				vector3df newPos(static_cast<float>(finalTranslation.X()), static_cast<float>(finalTranslation.Y()), static_cast<float>(finalTranslation.Z()));
				activePilar->GetDataSceneNode()->setPosition(newPos);
			}
			activePilar->Update2DMesh();

			imp_.ModifyPar_ = curPar;
		}
		break;
	case EPilarState::EPS_MOUSEHOLDING:
		{
			auto activePillar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());
			activePillar->SetPicking(true);

			if ( imp_.SavePos_.getDistanceFromSQ(imp_.CurrentPos_) > 100 * 100 )
			{
				imp_.State_ = EPilarState::EPS_MOVING;
				imp_.Valid_ = true;
			}
			else 
				if ( imp_.LMouseLeftUp_ )
				{
					imp_.PropertyCallBack_ = boost::none;
					imp_.State_ = EPilarState::EPS_PROPERTY;

					auto pointer = reinterpret_cast<int>(static_cast<void*>(&(*imp_.EventInfo_)));
					::PostMessage((HWND)GetRenderContextSPtr()->GetHandle(), WM_IRR_DLG_MSG, WM_USER_ROOMLAYOUT_PILLAR_PROPERTY, pointer);
				}
		}
		break;
	case EPilarState::EPS_PROPERTY:
		{
			if ( !imp_.PropertyCallBack_ )
			{
				break;
			}

			auto activePillar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());

			switch (*(imp_.PropertyCallBack_))
			{
			case EUT_ROOMLAYOUT_PILLAR_NONE:
				{
					imp_.State_ = EPilarState::EPS_SWEEPING;
				}
				break;
			case EUT_ROOMLAYOUT_PILLAR_UPDATE:
				{
					activePillar->SetSize(imp_.EventInfo_->XLength_, imp_.EventInfo_->YLength_, imp_.EventInfo_->ZLength_);
					activePillar->SetOffsetHeight(imp_.EventInfo_->OffsetHeight_);

					{
						auto curTrans = activePillar->GetTranslation();
						curTrans.SetY(imp_.EventInfo_->YLength_/2 + imp_.EventInfo_->OffsetHeight_);
						activePillar->SetTranslation(curTrans);

						auto curPos = activePillar->GetDataSceneNode()->getPosition();
						curPos.Y = static_cast<float>(imp_.EventInfo_->YLength_/2 + imp_.EventInfo_->OffsetHeight_);
						activePillar->GetDataSceneNode()->setPosition(curPos);
					}

					activePillar->UpdateMesh();
					imp_.State_ = EPilarState::EPS_SWEEPING;
				}
				break;
			case EUT_ROOMLAYOUT_PILLAR_MOVE:
				{
					imp_.State_ = EPilarState::EPS_MOVING;
				}
				break;
			case EUT_ROOMLAYOUT_PILLAR_DELETE:
				{
					activePillar->RemoveFromParent();
					imp_.State_ = EPilarState::EPS_SWEEPING;
				}
				break;
			default:
				assert(0);
				break;
			}
		}
		break;
	case EPilarState::EPS_CREATING_INIT:
		{
			assert(imp_.EventInfo_);

			auto newPilar = PillarODL::Create<PillarODL>(GetRenderContextSPtr());
			newPilar->SetSize(imp_.EventInfo_->XLength_, imp_.EventInfo_->YLength_, imp_.EventInfo_->ZLength_);
			newPilar->SetOffsetHeight(imp_.EventInfo_->OffsetHeight_);
			newPilar->UpdateMesh();

			RootODL_.lock()->AddChild(newPilar);

			auto newPos = imp_.CurrentPos_;
			newPos.Y = imp_.EventInfo_->YLength_/2;

			newPilar->SetTranslation(gp_XYZ(newPos.X, newPos.Y, newPos.Z));
			newPilar->GetDataSceneNode()->setPosition(newPos);
			SetPickingODL(newPilar);

			imp_.State_ = EPilarState::EPS_MOVING;
		}
		break;
	case EPilarState::EPS_MOVING:
		{
			auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());
			activePilar->SetPicking(true);
			activePilar->SetVaildPosition(imp_.Valid_);

			if ( imp_.LMouseLeftUp_ )
			{
				if ( imp_.Valid_ )
				{
					ImpUPtr_->Valid_ = false;
					ImpUPtr_->EventInfo_ = boost::none;

					imp_.State_ = EPilarState::EPS_SWEEPING;
					break;
				}
			}

			if ( imp_.EscapePressDown_ )
			{
				activePilar->RemoveFromParent();

				imp_.State_ = EPilarState::EPS_SWEEPING;
				break;
			}
			
			//当前柱的Box
			auto activeTransitionBox = activePilar->GetBaseBndBox();
			{
				gp_Trsf tfs;
				tfs.SetTranslationPart(activePilar->GetTranslation());
				activeTransitionBox = activeTransitionBox.Transformed(tfs);
			}

			activePilar->SetRotation(gp_Quaternion(gp::DZ(), gp::DZ()));
			activePilar->GetDataSceneNode()->setRotation(vector3df(0));

			auto size = activePilar->GetSize();
			auto offset = activePilar->GetOffsetHeight();

			//新的位置
			auto newPos = imp_.CurrentPos_;
			newPos.Y = static_cast<float>(size.Y()/2) + offset;
			gp_Pnt newPnt(newPos.X, newPos.Y, newPos.Z);

			//吸附距离
			static auto alignDis = 200.0;

			//当前的吸附物体
			auto alignODLs = activePilar->GetAlignList();
			alignODLs.erase(std::remove_if(alignODLs.begin(), alignODLs.end(), [&activePilar, &activeTransitionBox](const BaseODLSPtr& alignODL)
			{
				if ( !alignODL )
				{
					return true;
				}

				return alignODL->GetBaseBndBox().Distance(activeTransitionBox.Transformed(alignODL->GetAbsoluteTransform().Inverted())) > alignDis;
			}), alignODLs.end());
			activePilar->SetAlignList(BaseODLList());

			std::multimap<double,BaseODLSPtr> disMap;
			for ( auto& curODL : RootODL_.lock()->GetChildrenList() )
			{
				if ( EODLT_PILLAR != curODL->GetType() && EODLT_WALL != curODL->GetType() )
				{
					continue;
				}

				if ( std::find(alignODLs.begin(), alignODLs.end(), curODL) != alignODLs.end() )
				{
					continue;
				}

				if ( EODLT_PILLAR == curODL->GetType() && curODL == activePilar )
				{
					continue;
				}

				auto dis = curODL->GetBaseBndBox().Distance(activeTransitionBox.Transformed(curODL->GetAbsoluteTransform().Inverted()));
				if ( dis > alignDis )
				{
					continue;
				}

				disMap.emplace(dis, curODL);
			}

			for ( auto& curODL : disMap )
			{
				alignODLs.push_back(curODL.second);
			}

			//锁定旋转
			auto lockRotation = false;
			//锁定位置
			auto lockPosition = false;
			//移动方向
			TopoDS_Edge movingEdge;
			for ( auto& curODL : alignODLs )
			{
				auto alignTransformation = curODL->GetAbsoluteTransform();

				//如果锁定了旋转,则调整柱的box
				auto activeRotationPillarBox = activePilar->GetBaseBndBox();
				if ( lockRotation )
				{
					gp_Trsf tfsODL, tfsPillar;

					tfsODL.SetRotation(alignTransformation.GetRotation());
					tfsPillar.SetRotation(activePilar->GetRotation());

					activeRotationPillarBox = activeRotationPillarBox.Transformed(tfsODL.Inverted() * tfsPillar);
				}
				
				Bnd_Box movingBox;
				{
					auto curBox = curODL->GetBaseBndBox();

					Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax;
					curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax);

					Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax;
					activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax);

					movingBox.Update(xAlignMin+xPillarMin, yAlignMin+yPillarMin, zAlignMin+zPillarMin,
						xAlignMax+xPillarMax, yAlignMax+yPillarMax, zAlignMax+zPillarMax);
				}
				
				auto inODLPnt = newPnt.Transformed(curODL->GetAbsoluteTransform().Inverted());

				//当位置锁定了以后,只需要判断是不是相交
				if ( lockPosition )
				{
					if ( Standard_True == movingBox.IsOut(inODLPnt) )
					{
						continue;
					}

					Bnd_Box pntBox;
					pntBox.Add(inODLPnt);

					if ( pntBox.Distance(movingBox) < Precision::Confusion() )
					{
						continue;
					}

					imp_.Valid_ = false;
					break;
				}

				Bnd_Box alignODLBox;
				{
					auto curBox = curODL->GetBaseBndBox();

					Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax;
					curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax);

					Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax;
					activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax);

					alignODLBox.Update(xAlignMin+xPillarMin-alignDis, yAlignMin+yPillarMin-alignDis, zAlignMin+zPillarMin-alignDis,
						xAlignMax+xPillarMax+alignDis, yAlignMax+yPillarMax+alignDis, zAlignMax+zPillarMax+alignDis);
				}

				if ( Standard_True == alignODLBox.IsOut(inODLPnt) )
				{
					continue;
				}

				//当前被停靠物体的box shape
				Standard_Real xMin,yMin,zMin,xMax,yMax,zMax;
				movingBox.Get(xMin, yMin, zMin, xMax, yMax, zMax);
				auto alignBoxShape = BRepPrimAPI_MakeBox(gp_Pnt(xMin, yMin, zMin), gp_Pnt(xMax, yMax, zMax)).Shape();
				TopExp_Explorer exp(alignBoxShape, TopAbs_SHELL);

				if ( !lockRotation )
				{//找到第一个被停靠物体
					BRepExtrema_DistShapeShape dss(BRepBuilderAPI_MakeVertex(inODLPnt).Shape(), exp.Current());
					assert(0 != dss.NbSolution());
					inODLPnt = dss.PointOnShape2(1);

					newPnt = inODLPnt.Transformed(curODL->GetAbsoluteTransform()).XYZ();

					auto rot = curODL->GetAbsoluteTransform().GetRotation();
					Standard_Real rX,rY,rZ;
					rot.GetEulerAngles(gp_Extrinsic_XYZ, rX, rY, rZ);
					vector3df rotation(static_cast<float>(irr::core::radToDeg(rX)), static_cast<float>(irr::core::radToDeg(rY)), static_cast<float>(irr::core::radToDeg(rZ)));

					activePilar->GetDataSceneNode()->setRotation(rotation);
					activePilar->SetRotation(rot);

					gp_Dir movingDir;
					if ( std::abs(std::abs(inODLPnt.X()) - xMax) < Precision::Confusion() )
					{
						movingDir = gp::DZ();
					}
					else
					{
						movingDir = gp::DX();
					}
					auto curMovingEdge = BRepBuilderAPI_MakeEdge(gp_Lin(inODLPnt, movingDir)).Edge();

					movingEdge = TopoDS::Edge(curMovingEdge.Moved(curODL->GetAbsoluteTransform()));

					activePilar->AddAlign(curODL);
					imp_.Valid_ = true;
					lockRotation = true;
				}
				else
				{//第二个被停靠物体
					BRepExtrema_DistShapeShape dss(movingEdge.Moved(curODL->GetAbsoluteTransform().Inverted()), exp.Current());
					
					auto foundSecond = false;
					std::map<double, gp_Pnt> tmp;
					for ( auto index=1; index<=dss.NbSolution(); ++index )
					{
						auto pntOnEdge = dss.PointOnShape1(index);
						auto pntOnBox = dss.PointOnShape2(index);

						if ( pntOnEdge.Distance(pntOnBox) > Precision::Confusion() )
						{
							continue;
						}

						tmp.emplace(pntOnEdge.Distance(inODLPnt), pntOnEdge);
						foundSecond = true;
					}

					if ( !foundSecond )
					{
						imp_.Valid_ = false;
						break;
					}

					newPnt = tmp.begin()->second.Transformed(curODL->GetAbsoluteTransform());
					activePilar->AddAlign(curODL);
					lockPosition = true;
				}
			}

			if ( activePilar->GetAlignList().empty() )
			{
				imp_.Valid_ = true;
			}

			newPos.X = static_cast<float>(newPnt.X());
			newPos.Y = static_cast<float>(newPnt.Y());
			newPos.Z = static_cast<float>(newPnt.Z());
			activePilar->GetDataSceneNode()->setPosition(newPos);
			activePilar->SetTranslation(newPnt.XYZ());

			for ( auto& curAlign : activePilar->GetAlignList() )
			{
				curAlign->SetSweeping(true);
			}
		}
		break;
	default:
		break;
	}

	imp_.LMousePressDown_ = false;
	imp_.LMouseLeftUp_ = false;
	imp_.EscapePressDown_ = false;

	return false;
}