Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

GET THE FACE COLOR OF ANY FACE OF THE SOLID AND TURN IT THE OBJECT COLOR

9 REPLIES 9
SOLVED
Reply
Message 1 of 10
gustavobernardi
569 Views, 9 Replies

GET THE FACE COLOR OF ANY FACE OF THE SOLID AND TURN IT THE OBJECT COLOR

Hi everyone.

I receiveid a exported project which the objects colors are set as "By block", but it does have a color.

I'm not shure how to discover if the faces are "painted" with the color face sub-command, but slicing it, the new faces receive the White color (Byblock) so I'm almost certain of this.

My goal is to get the color of any face of each object and turn it the color of the main object itself.

I think the way is to convert the set of faces of each object into a list and get the head of this list, then the color, but I don't know how to get this properties. 

As it is a lot of objects, my intent is to not select the object for geting the face, I'll use the entire drawing selection (as the colors are result of an exportation it is consistently painted so doesn't matter which face I select).

Getting this result I'm able to convert the color to a layer with one code I already have.   

TIA

9 REPLIES 9
Message 2 of 10
pendean
in reply to: gustavobernardi

Share your DWG with that content here please.
Message 3 of 10

Unfortunately, the entity data for 3D Solids is utterly inscrutable, so I'm not sure it's possible to pull things like that out of it.  I tried giving some distinctive color numbers to faces of a 3D Solid, and couldn't find those numbers anywhere in entity data, nor in VLA properties, nor in (getpropertyvalue) properties, nor in extended data [that coloring doesn't create any].  I don't know where else to look for it, but maybe it's available somehow.

Kent Cooper, AIA
Message 4 of 10
Sea-Haven
in reply to: gustavobernardi

What does a dxfout of a 3d object reveal ? ACIS solid details comes to mine a huge minefield of information. To confusing for this average person.

A Google "spatial's acis solid modeling format" lots of info.

SeaHaven_0-1704265119460.png

 

Message 5 of 10
_gile
in reply to: gustavobernardi

Hi,

As said by @Kent1Cooper and @Sea-Haven this cannot be done with LISP, but it is doable with .NET.

Here's an example which defines a RESETFACESCOLOR command.

C# code:

 

using Autodesk.AutoCAD.ApplicationServices.Core;
using Autodesk.AutoCAD.BoundaryRepresentation;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

using System;
using System.Linq;

namespace SolidFacesColorSample
{
    public class Commands
    {
        [CommandMethod("RESETFACESCOLOR")]
        public void ResetFacesColor()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            var filter = new SelectionFilter(new[] { new TypedValue(0, "3DSOLID") });
            var selection = ed.GetSelection(filter);
            if (selection.Status == PromptStatus.OK)
            {
                using (var tr = db.TransactionManager.StartTransaction())
                {
                    foreach (var id in selection.Value.GetObjectIds())
                    {
                        var solid = (Solid3d)tr.GetObject(id, OpenMode.ForWrite);
                        SetFacesColor(solid, solid.Color);
                    }
                    tr.Commit();
                }
            }
        }

        private static void SetFacesColor(Solid3d solid, Color color)
        {
            var fullSubentityPath = new FullSubentityPath(
                        new[] { solid.ObjectId },
                        new SubentityId(SubentityType.Null, IntPtr.Zero));
            using (var brep = new Brep(fullSubentityPath))
            {
                var subentIds = brep.Faces
                    .Select(f => f.SubentityPath.SubentId)
                    .ToArray();
                foreach (var subentId in subentIds)
                {
                    solid.SetSubentityColor(subentId, color);
                }
            }
        }
    }
}

 

 

If you trust me enough to download and run a compiled application (I think you can):

  • Download the attached SolidFacesColorSample.zip.
  • Unblock the ZIP file.
  • Extract the SolidFacesColorSample.dll in some local directory.
  • Netload the DLL from AutoCAD (NETLOAD command).
  • Run the RESETFACESCOLOR command.


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 6 of 10
Sea-Haven
in reply to: gustavobernardi

Great answer Gile,  a typo in the instructions maybe, we all make them, our brain thinks faster than we type.

  • Run the RESETFALCESCOLOR command. 
  • should it be ?
  • Run the RESETFACESCOLOR command.
Message 7 of 10
_gile
in reply to: Sea-Haven


@Sea-Haven wrote:

Great answer Gile,  a typo in the instructions maybe, we all make them, our brain thinks faster than we type.

  • Run the RESETFALCESCOLOR command. 
  • should it be ?
  • Run the RESETFACESCOLOR command.

Thanks for reporting, I'll correct my reply.

 

Anyway, I was wrong, it can be done with LISP by sripting the SOLIDEDIT command. The following code should work in most of the cases (the solid centroid have to be projected on a face of the solid according to the view).

 

EDIT: wrap the (command ...) in a (vl-catch-all-apply ...) expression so that the routinedoes not stop if it fail for some solid.

 

(defun c:SetFacesByBlock (/ getCentroid ss i)
  
  (defun getCentroid (solid)
    (trans (vlax-get (vlax-ename->vla-object solid) 'Centroid) 0 1)
  )

  (if (setq ss (ssget '((0 . "3DSOLID"))))
    (repeat (setq i (sslength ss))
      (vl-catch-all-apply
	'(lambda (/ solid point)
	   (setq solid (ssname ss (setq i (1- i)))
		 point (getCentroid solid)
	   )
	   (command-s "_.solidedit"
		      "_face"
		      "_color"
		      point
		      "_all"
		      ""
		      "ByBlock"
		      ""
		      ""
	   )
	 )
      )
    )
  )
  (princ)
)

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 8 of 10
Kent1Cooper
in reply to: _gile

But I believe they are not trying to assign "ByBlock" to all faces, but to extract the color assigned to a face, and assign that as a property of the overall object, not its faces.  @gustavobernardi, am I correct about that?

Kent Cooper, AIA
Message 9 of 10
_gile
in reply to: Kent1Cooper


@Kent1Cooper wrote:

But I believe they are not trying to assign "ByBlock" to all faces, but to extract the color assigned to a face, and assign that as a property of the overall object, not its faces.  @gustavobernardi, am I correct about that?


Oops! I misunderstood the request (my English is not that good...)

Attached a new DLL with an additional command: SETCOLORFROMFACE which set the color of the selected solids with color ByBlock to the first find face color (if any).

[CommandMethod("SETCOLORFROMFACE")]
public static void SetColorFromFace()
{
    var doc = Application.DocumentManager.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;

    var filter = new SelectionFilter(new[] { 
        new TypedValue(0, "3DSOLID"),
        new TypedValue(62, 0)});
    var selection = ed.GetSelection(filter);
    if (selection.Status == PromptStatus.OK)
    {
        using (var tr = db.TransactionManager.StartTransaction())
        {
            foreach (var id in selection.Value.GetObjectIds())
            {
                var solid = (Solid3d)tr.GetObject(id, OpenMode.ForRead);
                if (TryGetFaceColor(solid, out Color color))
                {
                    tr.GetObject(id, OpenMode.ForWrite);
                    solid.Color = color;
                }
            }
            tr.Commit();
        }
    }
}

private static bool TryGetFaceColor(Solid3d solid, out Color color)
{
    color = default;
    var fullSubentityPath = new FullSubentityPath(
                new[] { solid.ObjectId },
                new SubentityId(SubentityType.Null, IntPtr.Zero));
    using (var brep = new Brep(fullSubentityPath))
    {
        var subentIds = brep.Faces
            .Select(f => f.SubentityPath.SubentId)
            .ToArray();
        foreach (var subentId in subentIds)
        {
            try
            {
                color = solid.GetSubentityColor(subentId);
                break;
            }
            catch { }
        }
    }
    return color != default;
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 10 of 10
gustavobernardi
in reply to: _gile

That's it! Perfect! It's exectly what I needed.

Thank you a lot!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report