Пример #1
0
        // 由布尔操作类型和两个三维实体创建旋转体的函数.
        public static void AddBoolSolid(BooleanOperationType boolType, ObjectId solid3dId1, ObjectId solid3dId2)
        {
            Database db = HostApplicationServices.WorkingDatabase;

            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                try
                {
                    Entity ent1 = (Entity)trans.GetObject(solid3dId1, OpenMode.ForWrite);
                    Entity ent2 = (Entity)trans.GetObject(solid3dId2, OpenMode.ForWrite);
                    if (ent1 is Solid3d & ent2 is Solid3d)
                    {
                        Solid3d solid3dEnt1 = (Solid3d)ent1;
                        Solid3d solid3dEnt2 = (Solid3d)ent2;
                        solid3dEnt1.BooleanOperation(boolType, solid3dEnt2);
                        ent2.Erase();
                    }
                    if (ent1 is Region & ent2 is Region)
                    {
                        Region regionEnt1 = (Region)ent1;
                        Region regionEnt2 = (Region)ent2;
                        regionEnt1.BooleanOperation(boolType, regionEnt2);
                        ent2.Erase();
                    }
                }
                catch
                {
                    // 此处无需要操作.
                }
                trans.Commit();
            }
        }
 protected BaseOperation(IQuery query, BooleanOperationType type)
 {
     _query        = query;
     OperationType = type;
     // the compiler will build our query-dsl. switch it out to custom impl if you wish to build your own query service
     _compiler = new DefaultQueryCompiler();
 }
Пример #3
0
        /// <summary>
        /// 由布尔操作函数创建三维实体
        /// </summary>
        /// <param name="boolType">布尔操作类型</param>
        /// <param name="solid3dId1">参与操作的三维实体的Id</param>
        /// <param name="solid3dId2">参与操作的三维实体的Id</param>
        /// <returns>返回创建的三维实体的Id</returns>
        public static bool BoolSolid3dRegion(BooleanOperationType boolType,
                                             ObjectId solid3dId1, ObjectId solid3dId2)
        {
            Database db = HostApplicationServices.WorkingDatabase;
            Editor   ed = Application.DocumentManager.MdiActiveDocument.Editor;

            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                try
                {
                    Entity ent1 = trans.GetObject(solid3dId1, OpenMode.ForWrite) as Entity;
                    Entity ent2 = trans.GetObject(solid3dId2, OpenMode.ForWrite) as Entity;

                    if (ent1 == null || ent2 == null)
                    {
                        ed.WriteMessage("\n布尔操作失败!");
                        return(false);
                    }

                    if (ent1 is Solid3d & ent2 is Solid3d)
                    {
                        Solid3d solid3dEnt1 = (Solid3d)ent1;
                        Solid3d solid3dEnt2 = (Solid3d)ent2;
                        solid3dEnt1.BooleanOperation(boolType, solid3dEnt2);
                        ent2.Dispose();
                    }

                    if (ent1 is Region & ent2 is Region)
                    {
                        Region regionEnt1 = (Region)ent1;
                        Region regionEnt2 = (Region)ent2;
                        regionEnt1.BooleanOperation(boolType, regionEnt2);
                        ent2.Dispose();
                    }
                }
                catch
                {
                    ed.WriteMessage("\n布尔操作失败!");
                    return(false);
                }
                trans.Commit();
                return(true);
            }
        }
Пример #4
0
 /// <summary>
 /// 三维实体布尔运算
 /// </summary>
 /// <param name="solid1"></param>
 /// <param name="solid2"></param>
 /// <param name="type"></param>
 public static Solid3d BooleanOper(Solid3d solid1, Solid3d solid2, BooleanOperationType type)
 {
     solid1.BooleanOperation(type, solid2);
     return(solid1);
 }
        //-----------------------------------------------------------------------
        //
        //ORIGINAL LINE: MultiShape _booleanOperation(const Shape& STLAllocator<U, AllocPolicy>, BooleanOperationType opType) const
        private MultiShape _booleanOperation(Shape other, BooleanOperationType opType) {
            if (!mClosed || mPoints.size() < 2)
                OGRE_EXCEPT("Ogre::Exception::ERR_INVALID_STATE", "Current shapes must be closed and has to contain at least 2 points!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)");
            if (!other.mClosed || other.mPoints.size() < 2)
                OGRE_EXCEPT("Ogre::Exception::ERR_INVALIDPARAMS", "Other shapes must be closed and has to contain at least 2 points!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)");
            ;

            // Compute the intersection between the 2 shapes
            std_vector<IntersectionInShape> intersections = new std_vector<IntersectionInShape>();
            _findAllIntersections(other, ref intersections);

            // Build the resulting shape
            if (intersections.empty()) {
                if (isPointInside(other.getPoint(0))) {
                    // Shape B is completely inside shape A
                    if (opType == BooleanOperationType.BOT_UNION) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(this);
                        return ms;
                    }
                    else if (opType == BooleanOperationType.BOT_INTERSECTION) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(other);
                        return ms;
                    }
                    else if (opType == BooleanOperationType.BOT_DIFFERENCE) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(this);
                        ms.addShape(other);
                        ms.getShape(1).switchSide();
                        return ms;
                    }

                }
                else if (other.isPointInside(getPoint(0))) {
                    // Shape A is completely inside shape B
                    if (opType == BooleanOperationType.BOT_UNION) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(other);
                        return ms;
                    }
                    else if (opType == BooleanOperationType.BOT_INTERSECTION) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(this);
                        return ms;
                    }
                    else if (opType == BooleanOperationType.BOT_DIFFERENCE) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(this);
                        ms.addShape(other);
                        ms.getShape(0).switchSide();
                        return ms;
                    }
                }
                else {
                    if (opType == BooleanOperationType.BOT_UNION) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(this);
                        ms.addShape(other);
                        return ms;
                    }
                    else if (opType == BooleanOperationType.BOT_INTERSECTION)
                        return new MultiShape(); //empty result
                    else if (opType == BooleanOperationType.BOT_DIFFERENCE)
                        return new MultiShape(); //empty result
                }
            }
            MultiShape outputMultiShape = new MultiShape();

            Shape[] inputShapes = new Shape[2];
            inputShapes[0] = this;
            inputShapes[1] = other;

            while (!intersections.empty()) {
                Shape outputShape = new Shape();
                byte shapeSelector = 0; // 0 : first shape, 1 : second shape

                Vector2 currentPosition = intersections[0].position;//intersections.GetEnumerator().position;
                IntersectionInShape firstIntersection = intersections[0];//*intersections.GetEnumerator();
                uint currentSegment = firstIntersection.index[shapeSelector];
                //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent to the STL vector 'erase' method in C#:
                //intersections.erase(intersections.GetEnumerator());//ÒƳý
                intersections.erase(firstIntersection, true);
                outputShape.addPoint(currentPosition);

                sbyte isIncreasing = 0; // +1 if increasing, -1 if decreasing, 0 if undefined

                if (!_findWhereToGo(inputShapes, opType, firstIntersection, ref shapeSelector, ref isIncreasing, ref currentSegment)) {
                    // That intersection is located on a place where the resulting shape won't go => discard
                    continue;
                }

                while (true) {
                    // find the closest intersection on the same segment, in the correct direction
                    //List<IntersectionInShape>.Enumerator found_next_intersection = intersections.end();
                    IntersectionInShape found_next_intersection = intersections[intersections.Count - 1];
                    int found_next_intersection_pos = -1;
                    float distanceToNextIntersection = float.MaxValue;// std.numeric_limits<Real>.max();

                    uint nextPoint = currentSegment + (uint)(isIncreasing == 1 ? 1 : 0);
                    bool nextPointIsOnIntersection = false;

                    //for (List<IntersectionInShape>.Enumerator it = intersections.GetEnumerator(); it.MoveNext(); ++it)
                    for (int i = 0; i < intersections.Count; i++) {
                        IntersectionInShape it = intersections[i];
                        if (currentSegment == it.index[shapeSelector]) {
                            if (((it.position - currentPosition).DotProduct(it.position - inputShapes[shapeSelector].getPoint((int)nextPoint)) < 0f) || (it.onVertex[shapeSelector] && nextPoint == it.index[shapeSelector])) {
                                // found an intersection between the current one and the next segment point
                                float d = (it.position - currentPosition).Length;
                                if (d < distanceToNextIntersection) {
                                    // check if we have the nearest intersection
                                    found_next_intersection = it;
                                    found_next_intersection_pos = i;
                                    distanceToNextIntersection = d;
                                }
                            }
                        }
                        if (nextPoint == it.index[shapeSelector] && it.onVertex[shapeSelector])
                            nextPointIsOnIntersection = true;
                    }

                    // stop condition
                    if (currentSegment == firstIntersection.index[shapeSelector]) {
                        // we found ourselves on the same segment as the first intersection and no other
                        if ((firstIntersection.position - currentPosition).DotProduct(firstIntersection.position - inputShapes[shapeSelector].getPoint((int)nextPoint)) < 0f) {
                            float d = (firstIntersection.position - currentPosition).Length;
                            if (d > 0.0f && d < distanceToNextIntersection) {
                                outputShape.close();
                                break;
                            }
                        }
                    }

                    // We actually found the next intersection => change direction and add current intersection to the list
                    //if (found_next_intersection.MoveNext())
                    //if (intersections.Count > 1) {
                    if (found_next_intersection_pos != -1) {
                        //IntersectionInShape currentIntersection = found_next_intersection.Current;
                        IntersectionInShape currentIntersection = found_next_intersection;

                        intersections.erase(found_next_intersection, true);
                        //IntersectionInShape currentIntersection = intersections[intersections.Count - 1];
                        outputShape.addPoint(currentIntersection.position);
                        bool result = _findWhereToGo(inputShapes, opType, currentIntersection, ref shapeSelector, ref isIncreasing, ref currentSegment);
                        if (result == null) {
                            OGRE_EXCEPT("Ogre::Exception::ERR_INTERNAL_ERROR", "We should not be here!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)");
                            ;
                        }
                    }
                    else {
                        // no intersection found for the moment => just continue on the current segment
                        if (!nextPointIsOnIntersection) {
                            if (isIncreasing == 1)
                                currentPosition = inputShapes[shapeSelector].getPoint((int)currentSegment + 1);
                            else
                                currentPosition = inputShapes[shapeSelector].getPoint((int)currentSegment);

                            outputShape.addPoint(currentPosition);
                        }
                        currentSegment = (uint)Utils.modulo((int)currentSegment + isIncreasing, inputShapes[shapeSelector].getSegCount());
                    }
                }

                outputMultiShape.addShape(outputShape);
            }
            return outputMultiShape;
        }
        //-----------------------------------------------------------------------
        //
        //ORIGINAL LINE: bool _findWhereToGo(const Shape* inputShapes[], BooleanOperationType opType, IntersectionInShape intersection, byte& shapeSelector, sbyte& isIncreasing, uint& currentSegment) const
        private bool _findWhereToGo(Shape[] inputShapes, BooleanOperationType opType, IntersectionInShape intersection, ref byte shapeSelector, ref sbyte isIncreasing, ref uint currentSegment) {
            if (intersection.onVertex[0] || intersection.onVertex[1]) {
                // determine 4 directions with normal info
                // if 2 normals "face each other" then you have the couple of outside directions
                Vector2[] directions = new Vector2[4];
                //string sides = new string(new char[4]);
                byte[] sides = new byte[4];
                byte incomingDirection;

                // fill-in the incoming arrays
                if (isIncreasing == 0) {
                    incomingDirection = 255;
                }
                else {
                    incomingDirection = (byte)(shapeSelector + (isIncreasing == 1 ? 2 : 0));
                }
                for (byte i = 0; i < 2; i++)
                    if (intersection.onVertex[i]) {
                        directions[i] = inputShapes[i].getDirectionBefore(intersection.index[i]);
                        directions[2 + i] = -inputShapes[i].getDirectionAfter(intersection.index[i]);
                    }
                    else {
                        directions[2 + i] = -inputShapes[i].getDirectionAfter(intersection.index[i]);
                        directions[i] = -directions[2 + i];
                    }
                for (byte i = 0; i < 4; i++) {
                    sides[i] = (byte)((i / 2 == 0 ? -1 : 1) * (inputShapes[i % 2].mOutSide == Side.SIDE_RIGHT ? -1 : 1));
                }

                bool[] isOutside = new bool[4];
                //std.pair<Radian, byte>[] sortedDirections = new std.pair[4];
                KeyValuePair<Radian, byte>[] sortedDirections = new KeyValuePair<Radian, byte>[4];
                // sort by angle
                for (byte i = 0; i < 4; i++) {
                    if (i == 0) {
                        //sortedDirections[i].first = 0;
                        sortedDirections[i] = new KeyValuePair<Radian, byte>(0, i);
                    }
                    else {
                        Radian first = sides[0] * Utils.angleTo(directions[0], directions[i]);
                        sortedDirections[i] = new KeyValuePair<Radian, byte>(first, i);
                    }
                    //sortedDirections[i].second=i;
                }

                //std.sort(sortedDirections, sortedDirections+4, GlobalMembersProceduralShape._sortAngles);
                //ToDo:sortedDirectionsÅÅÐò
                List<KeyValuePair<Radian, byte>> sort_sortedDirections = new List<KeyValuePair<Radian, byte>>();
                sort_sortedDirections.AddRange(sortedDirections);
                sort_sortedDirections.Sort((X, Y) => {
                    return _sortAngles(X, Y) ? -1 : 1;
                });
                sortedDirections = sort_sortedDirections.ToArray();
                //Array.Sort(sortedDirections);
                //find which segments are outside
                if (sides[0] != sides[sortedDirections[1].Value]) {
                    isOutside[0] = isOutside[sortedDirections[1].Value] = true;
                    isOutside[sortedDirections[2].Value] = isOutside[sortedDirections[3].Value] = false;
                }
                else {
                    isOutside[sortedDirections[1].Value] = isOutside[sortedDirections[2].Value] = true;
                    isOutside[sortedDirections[3].Value] = isOutside[sortedDirections[0].Value] = false;
                }

                //find first eligible segment that is not the current segment
                for (ushort i = 0; i < 4; i++)
                    if ((isOutside[i] == _isLookingForOutside(opType, (sbyte)(i % 2))) && (i != incomingDirection)) {
                        shapeSelector = (byte)(i % 2);
                        isIncreasing = (sbyte)(i / 2 == 0 ? 1 : -1);
                        currentSegment = intersection.index[shapeSelector];
                        return true;
                    }
                // if we reach here, it means that no segment is eligible! (it should only happen with difference opereation
                return false;
            }
            else {
                // determine which way to go
                int nextShapeSelector = (shapeSelector + 1) % 2;

                float d = inputShapes[nextShapeSelector].getDirectionAfter(intersection.index[nextShapeSelector]).DotProduct(inputShapes[shapeSelector].getNormalAfter(currentSegment));
                isIncreasing = _isIncreasing(d, opType, (sbyte)nextShapeSelector);

                shapeSelector = (byte)nextShapeSelector;

                currentSegment = intersection.index[shapeSelector];
                return true;
            }
        }
 //-----------------------------------------------------------------------
 //
 //ORIGINAL LINE: sbyte _isIncreasing(float d, BooleanOperationType opType, sbyte shapeSelector) const
 private sbyte _isIncreasing(float d, BooleanOperationType opType, sbyte shapeSelector) {
     if (d < 0f && opType == BooleanOperationType.BOT_UNION)
         return -1;
     if (d > 0f && opType == BooleanOperationType.BOT_INTERSECTION)
         return -1;
     if (opType == BooleanOperationType.BOT_DIFFERENCE) {
         if ((d < 0f && shapeSelector == 0) || (d > 0f && shapeSelector == 1))
             return -1;
     }
     return 1;
 }
 //-----------------------------------------------------------------------
 //
 //ORIGINAL LINE: bool _isLookingForOutside(BooleanOperationType opType, sbyte shapeSelector) const
 private bool _isLookingForOutside(BooleanOperationType opType, sbyte shapeSelector) {
     switch (opType) {
         case BooleanOperationType.BOT_UNION:
             return true;
         case BooleanOperationType.BOT_INTERSECTION:
             return false;
         case BooleanOperationType.BOT_DIFFERENCE:
             if (shapeSelector == 0)
                 return true;
             return false;
         default:
             return true;
     }
 }