Announcements
Attention for Customers without Multi-Factor Authentication or Single Sign-On - OTP Verification rolls out April 2025. Read all about it here.

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

gustavobernardi
Advocate

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

gustavobernardi
Advocate
Advocate

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

0 Likes
Reply
Accepted solutions (1)
795 Views
9 Replies
Replies (9)

pendean
Community Legend
Community Legend
Share your DWG with that content here please.
0 Likes

Kent1Cooper
Consultant
Consultant

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
0 Likes

Sea-Haven
Mentor
Mentor

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

 

0 Likes

_gile
Mentor
Mentor

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

0 Likes

Sea-Haven
Mentor
Mentor

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.
0 Likes

_gile
Mentor
Mentor

@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

0 Likes

Kent1Cooper
Consultant
Consultant

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
0 Likes

_gile
Mentor
Mentor
Accepted solution

@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

0 Likes

gustavobernardi
Advocate
Advocate

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

Thank you a lot!

0 Likes