Author Topic: how to move a face in a solid ?  (Read 12639 times)

0 Members and 1 Guest are viewing this topic.

bikelink

  • Guest
how to move a face in a solid ?
« on: June 02, 2010, 02:02:11 AM »
I'm trying to move a face in a solid3d  via code . You can consider a simple box. I'm not able to understand how can I obtain the SubEntityID[]
needed to perform the methods without selection


SubentityId[] subEntsID = ????
mySolid.ExtrudeFaces(subEntsID, 100, 0);

s.TransformFaces(????,ecc..)


thanks in advance for any idea!

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: how to move a face in a solid ?
« Reply #1 on: June 02, 2010, 02:09:52 AM »

Quote
... perform the methods without selection


What does your program know about the solid ??

how will the program know which face to move ??

what have you tried ??

are you familiar with   acdbmgdbrep.dll ??
 
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

bikelink

  • Guest
Re: how to move a face in a solid ?
« Reply #2 on: June 02, 2010, 02:16:36 AM »
ok...


Code: [Select]
using (Transaction t = d.TransactionManager.StartTransaction())
                {
                    Solid3d s = t.GetObject(IdSolid3d, OpenMode.ForWrite) as Solid3d;
                   
                   
                   
                    //// found the face...
                    using (AcBr.Brep brp = new AcBr.Brep(s))
                    {
                        ObjectId[] ids = new ObjectId[1];
                        ids[0] = s.ObjectId;
                        SubentityId index = new SubentityId(SubentityType.Null, 0);
                        FullSubentityPath path = new FullSubentityPath(ids, index);
                        s.Highlight(path, true);


                        Extents3d e =  s.GeometricExtents;
                        AcBr.BrepFaceCollection facce = brp.Faces;
                        IList<AcBr.Face> faccedaspostare = new List<AcBr.Face>(0);
                        foreach (AcBr.Face [color=blue]f[/color] in facce)
                        {
                            IList<Point3d> ptfaccia = new List<Point3d>(0);
                            AcBr.FaceLoopCollection fl =  f.Loops;
                            foreach (AcBr.BoundaryLoop l in fl)
                            {

so I Have a acbrface...and I Know the face that I want to move.
How can I get th subentityID about a face (or more faces) ?
And other question is ... Why the property "f.SubentityPath" just to see the value throws an exception ?


Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: how to move a face in a solid ?
« Reply #3 on: June 02, 2010, 03:47:20 AM »

can you post all the code and the drawing .. I'll try to have a look early tomorrow .. won't have much time , sorry.

Is the face you want planar ??
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

bikelink

  • Guest
Re: how to move a face in a solid ?
« Reply #4 on: June 02, 2010, 04:01:24 AM »
Code: [Select]
static public void MoveTopFacesOfSolid(Document d, ObjectId IdSolid3d, double hfinale,Vector3d vetextr)
        {
            using (DocumentLock lk = d.LockDocument())
            {
                using (Transaction t = d.TransactionManager.StartTransaction())
                {
                    Solid3d s = t.GetObject(IdSolid3d, OpenMode.ForWrite) as Solid3d;
                    
                    
                    
                    //// found the face...
                    using (AcBr.Brep brp = new AcBr.Brep(s))
                    {
                        ObjectId[] ids = new ObjectId[1];
                        ids[0] = s.ObjectId;
                        SubentityId index = new SubentityId(SubentityType.Null, 0);
                        FullSubentityPath path = new FullSubentityPath(ids, index);
                        s.Highlight(path, true);


                        Extents3d e =  s.GeometricExtents;
                        AcBr.BrepFaceCollection facce = brp.Faces;
                        IList<AcBr.Face> faccedaspostare = new List<AcBr.Face>(0);
                        foreach (AcBr.Face f in facce)
                        {
                            IList<Point3d> ptfaccia = new List<Point3d>(0);
                            AcBr.FaceLoopCollection fl =  f.Loops;
                            foreach (AcBr.BoundaryLoop l in fl)
                            {
                                // se un cerchio
                                if (l.LoopType == Autodesk.AutoCAD.BoundaryRepresentation.LoopType.LoopWinding)
                                {
                                    foreach (AcBr.Edge filo in l.Edges)
                                    {
                                        Curve3d c = filo.Curve;

                                        Plane planz;
                                        bool b = c.IsPlanar(out planz);
                                        if (planz.Normal == vetextr)
                                        {
                                            faccedaspostare.Add(f);
                                        }
                                        planz.Dispose();
                                    }

                                }
                                else
                                {
                                    foreach (AcBr.Vertex v in l.Vertices)
                                    {
                                        ptfaccia.Add(v.Point);
                                    }
                                    // se la faccia è normale alla direzione...e siamo sopra.
                                    Vector3d vf = ptfaccia[0] - ptfaccia[1];
                                    Vector3d vfperp = vf.GetPerpendicularVector();
                                    Vector3d vfnorm = vf.CrossProduct(vfperp);
                                    if (vfnorm.IsParallelTo(vetextr) && ptfaccia[0].Z == e.MaxPoint.Z)
                                        faccedaspostare.Add(f);

                                }
                            }
                            
                              
                                //DoubleCollection Rad = new  DoubleCollection();
                                //Rad.Add(2.0);
                                //DoubleCollection startsetback = new DoubleCollection();
                                //startsetback.Add(0);
                                //DoubleCollection endsetback = new DoubleCollection();
                                //endsetback.Add(0);

                                //SubentityId[] sub1 = new SubentityId[] { new SubentityId(SubentityType.Edge, 0) };
                                //s.FilletEdges(sub1, Rad, startsetback,endsetback);

                                //SubentityId si = new SubentityId(SubentityType.Face, 0);
                            SubentityId[] sub2 = new SubentityId[] {  new SubentityId(SubentityType.Face, 0)};
                            
                                                                    
                            s.ExtrudeFaces(sub2, 100, 0);
                              
                                
                            }
                        }

                    t.Commit();
                }
            }
        
        }



[CommandMethod("mvts")]
         public void mvts()
         {
         Document d = (Document)Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
         Editor e = d.Editor;
             PromptEntityOptions o = new PromptEntityOptions("select a solid");
             o.SetRejectMessage("is not a  solid");
             PromptEntityResult r =  e.GetEntity(o);
             if (r.Status == PromptStatus.OK)
             {
                 MoveTopFacesOfSolid(d, r.ObjectId, 1000, Vector3d.ZAxis);
            
             }
         }

that's all..
The top faces  must be moved and i don't understand how can I take the entities :( without user selection
thanks for Your help. Any idea is always better of mine..now.
« Last Edit: June 02, 2010, 04:14:27 AM by bikelink »

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: how to move a face in a solid ?
« Reply #5 on: June 02, 2010, 05:14:19 PM »
without studying your code too much, if you can get the face, dig deeper to get each vertice (using the traversal classes) of the face from it's edges and transform the vertices and the edges and face should follow.
hth
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

bikelink

  • Guest
Re: how to move a face in a solid ?
« Reply #6 on: June 02, 2010, 11:46:24 PM »
no. it's not right.
1) You can't apply a transform at acbr vertex.
2) If You apply a transform at Point (property of vertex) nothing happens

 :realmad:


some words in Autodesk discussion groups sounds bad..like

There's little API support for solid modeling in AutoCAD
because Autodesk doesn't want them to be programmable.

http://discussion.autodesk.com/forums/thread.jspa?messageID=6356439&#6356439

I don't want to believe it and I'm sure that a solid could be modified in a dimension.. isn't it?
« Last Edit: June 03, 2010, 01:13:04 AM by bikelink »

SEANT

  • Bull Frog
  • Posts: 345
Re: how to move a face in a solid ?
« Reply #7 on: June 03, 2010, 04:21:37 AM »
I ran into this same issue when writing the routine in this post:
http://www.theswamp.org/index.php?topic=30499.0

At the time I assumed it was because the SubentID wasn’t created until it could be associated with the appropriate graphical elements. 

Now, looking at your situation where there shouldn’t be any problem getting Face.SubentityPath, it does seem a bit suspicious.

There may be more avenues to explore, I’ll post back if I find anything.
Sean Tessier
AutoCAD 2016 Mechanical

SEANT

  • Bull Frog
  • Posts: 345
Re: how to move a face in a solid ?
« Reply #8 on: June 04, 2010, 12:09:33 PM »
A couple of irritating quirks have come to light here:

It would appear that there is some initialization going on that does not occur with the Editor.GetEntity, hence the problem with “f.SubentityPath”.  The initialization is available with Solid3d.GetSubentityPathsAtGraphicsMarker, however, so it is possible to get a valid SubentID from the backside.

The other quirk is that the SubentityId[] requirement for all of the SolidEditing “Faces” methods is not implemented as the documentation states.  I can’t find an object/array that is compatible.  The SolidEditing “Face” methods do seem to work, and is what I used as a workaround in the sample.

Code: [Select]
        [CommandMethod("mvts")]
        public void mvts()
        {
            Document d = (Document)Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Editor e = d.Editor;


            PromptEntityOptions o = new PromptEntityOptions("select a solid");
            o.SetRejectMessage("is not a  solid");
            o.AddAllowedClass(typeof(Solid3d), true);
            PromptEntityResult r = e.GetEntity(o);
            if (r.Status == PromptStatus.OK)
            {
                MoveTopFacesOfSolid2(d, r.ObjectId, 1, Vector3d.ZAxis);

            }
        }


        static public void MoveTopFacesOfSolid2(Document d, ObjectId IdSolid3d, double hfinale, Vector3d vetextr)
        {

            using (Transaction t = d.TransactionManager.StartTransaction())
            {
               
                Solid3d s = t.GetObject(IdSolid3d, OpenMode.ForRead) as Solid3d;
                AcBr.Brep brp = new AcBr.Brep(s);
                Point3d pt = new Point3d();
                Matrix3d mtrx = new Matrix3d();
                int numIns = new int();
                ObjectId[] ids = null;
                FullSubentityPath[] fsP;
                for (int i = 1; i < 1000; i++)
                {
                    try
                    {
                        fsP = s.GetSubentityPathsAtGraphicsMarker
                            (SubentityType.Face, i, pt, mtrx, numIns, ids); //If GSM points to face
                        Autodesk.AutoCAD.BoundaryRepresentation.Face brepFace = new Autodesk.AutoCAD.BoundaryRepresentation.Face(fsP[0]);
                        if (TestFace(brepFace, vetextr))
                        {

                            s.UpgradeOpen();
                            SubentityId sid = fsP[0].SubentId;                                                                                                               
                            Region reg = s.CopyFace(sid) as Region;
                            Solid3d s2 = new Solid3d();
                                                                                                                                                                                                                                                                                                                  s2.Extrude(reg, 1, 0);
                            s2.SetDatabaseDefaults();
                            Database m_db = HostApplicationServices.WorkingDatabase;
                            BlockTableRecord btr = (BlockTableRecord)(t.GetObject(m_db.CurrentSpaceId, OpenMode.ForWrite));
                            btr.AppendEntity(s2);
                            t.AddNewlyCreatedDBObject(s2, true);


                            s.BooleanOperation(BooleanOperationType.BoolUnite, s2);
                            break;
                        }

                    }
                    catch //If GSM points to non-face
                    {
                        continue;
                    }

                }
                t.Commit();
            }
        }

        static public bool TestFace(AcBr.Face f, Vector3d vetextr)
        {
            ExternalBoundedSurface ebs = f.Surface as ExternalBoundedSurface;
            if (ebs.IsPlane)
            {
                Plane BP = ebs.BaseSurface as Plane;
                return BP.Normal == vetextr;

            }

            return false;
        }

Sean Tessier
AutoCAD 2016 Mechanical

bikelink

  • Guest
Re: how to move a face in a solid ?
« Reply #9 on: June 07, 2010, 08:29:48 AM »
ok...today i'll try as soon as possible Your solution. Thank You very much for your attention and code.

bikelink

  • Guest
Re: how to move a face in a solid ?
« Reply #10 on: June 14, 2010, 06:02:43 AM »
ok...today i'll try as soon as possible Your solution. Thank You very much for your attention and code.

that's Works!!!
Thank You very much SEANT! I haven't idea to loop around with
fsP = s.GetSubentityPathsAtGraphicsMarker
                            (SubentityType.Face, i, pt, mtrx, numIns, ids); //If GSM points to face
Autodesk.AutoCAD.BoundaryRepresentation.Face brepFace = new Autodesk.AutoCAD.BoundaryRepresentation.Face(fsP[0]);


and try/catch to iterate..
But for me is a  mistery the method exposed in api for brep.."extrudefaces"

SEANT

  • Bull Frog
  • Posts: 345
Re: how to move a face in a solid ?
« Reply #11 on: June 15, 2010, 03:31:49 AM »
But for me is a  mistery the method exposed in api for brep.."extrudefaces"

I agree.  That situation is rather irritating. 
Perhaps one of our C++ proficient brethren could test that in native ARX to see if and how those particular methods work.  :angel:
« Last Edit: June 15, 2010, 03:37:59 AM by SEANT »
Sean Tessier
AutoCAD 2016 Mechanical

ahlzl

  • Guest
Re: how to move a face in a solid ?
« Reply #12 on: June 15, 2010, 08:17:10 AM »
sorry,I do not speak English。

I can extrudeFace by ARX,but Wrapper to C#, fail! :oops:

Code: [Select]
static void ahlzlArxProject1_MyCommand1(void)
{
// Add your code for command ahlzlArxProject1._MyCommand1 here
AcDbObjectId entId = NULL;
AcDbEntity *pEnt;
AcDb3dSolid *pSolid3d;
AcArray<AcDbSubentId*> subIdArr;
AcEdSolidSubentitySelector subSel;

if (subSel.selectFaces(entId, subIdArr) == Acad::eOk)
{
if (acdbOpenAcDbEntity(pEnt, entId, AcDb::kForWrite) == Acad::eOk)
{
pSolid3d = (AcDb3dSolid*)pEnt;
for (int i = 0; i < subIdArr.length(); i++)
{
AcDbSubentId subId(AcDb::kFaceSubentType, subIdArr[i]->index());
pSolid3d->extrudeFaces(subIdArr, 100.0, 0.0);
}
pSolid3d->close();
}
}
}

SEANT

  • Bull Frog
  • Posts: 345
Re: how to move a face in a solid ?
« Reply #13 on: June 20, 2010, 06:10:21 AM »
ahlzl,

Thanks for testing that for me. 

It is a shame that the .NET wrapper is not working as expected.   :-(

I suppose this is another indication that stepping up to native ARX is a worthwhile endeavor.
Sean Tessier
AutoCAD 2016 Mechanical

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: how to move a face in a solid ?
« Reply #14 on: June 20, 2010, 07:05:17 AM »
I suppose this is another indication that stepping up to native ARX is a worthwhile endeavor.

Jump in, the water is fine  8-)