Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Using AVF on ductwork - Coordinates issue?

2 REPLIES 2
SOLVED
Reply
Message 1 of 3
phague
364 Views, 2 Replies

Using AVF on ductwork - Coordinates issue?

Hello, 

I am currently trying to create an add-in that will allow me to perform a calculation on various points on a duct face.

 

For now, the user is selecting the face, but in the future, I plan to process the top face of each duct in the view.

I am following along with the RvtFader example project.

A reference to my face is passed into the SpatialFieldManager, exactly like in the RvtFader example. 

The UpdateSpatialFieldPrimiate method runs without error, and my duct is shaded with a single solid color.

 

I believe my issue is that I am feeding the FieldDomainPointsByUV with UV points that are in the global coordinate system instead of the local coordinates system to the face. I suspect because create a BoundingBoxUV of my face, and supplying the bb.Min and bb.Max, along with 0, 10 as FieldValues, I get a correctly shaded (using a gradient) duct. 

 

Is there a way to convert WCS XYZ points to local UV points?

I assume I don't care about the z coordinate...

 

What am I missing here? 

 

Here is my relevant code:

 

 

      static SpatialFieldManager SetUpAvfSfm(View view, Reference faceReference, Face face)
        {
            if (view.AnalysisDisplayStyleId == ElementId.InvalidElementId)
            {
                SetAvfDisplayStyle(view);
            }

            SpatialFieldManager _sfm = SpatialFieldManager.GetSpatialFieldManager(view);

            if (null == _sfm)
            {
                _sfm = SpatialFieldManager.CreateSpatialFieldManager(view, 1);
            }
            else if (0 < _sfp_index)
            {
                _sfm.RemoveSpatialFieldPrimitive(_sfp_index);
            }

            _sfp_index = _sfm.AddSpatialFieldPrimitive(faceReference);

            if (_schemaId != -1)
            {
                List<int> results = _sfm.GetRegisteredResults().ToList();
                foreach (int idx in results)
                {

                }

                if (!results.Contains(_schemaId))
                {
                    _schemaId = -1;
                }
            }

            if (_schemaId == -1)
            {
                AnalysisResultSchema schema = new AnalysisResultSchema("Test", "Test Description");

                //List<string> unitNames = new List<string>(new string[1] { "Score" });
                //List<double> unitFactors = new List<double>(new double[1] { 1.0 });
                //schema.SetUnits(unitNames, unitFactors);
                if (_sfm.IsResultSchemaNameUnique("Test", -1))
                    _schemaId = _sfm.RegisterResult(schema);
                else
                {
                    List<int> existing = _sfm.GetRegisteredResults().ToList();
                    foreach (int idx in existing)
                    {
                        if (_sfm.GetResultSchema(idx).Name == "Test")
                        {
                            _schemaId = idx;
                            break;
                        }
                    }
                }

            }

            return _sfm;
        }

 

 private void PaintFace(Document doc, SpatialFieldManager sfm, Element element, Face face, Dictionary<XYZ, double> ductMap)
        {
            //BoundingBoxUV bb = face.GetBoundingBox();

            //UV min = bb.Min;
            //UV max = bb.Max;

            IList<UV> uvPts = new List<UV>();
            //uvPts.Add(bb.Min); // adding these points created a successful gradient
            //uvPts.Add(bb.Max); // adding these points created a successful gradient

            IList<ValueAtPoint> uvValues = new List<ValueAtPoint>();
            //uvValues.Add(new ValueAtPoint(new List<double> { 0.0 })); // adding these values created a successful gradient
            //uvValues.Add(new ValueAtPoint(new List<double> { 10.0 })); // adding these values created a successful gradient
            List<double> vals = new List<double>(1);
            vals.Add(0);
            
            
            foreach (KeyValuePair<XYZ, double> kvp in ductMap)
            {
                UV pt = new UV(kvp.Key.X, kvp.Key.Y);
                uvPts.Add(new UV(kvp.Key.X, kvp.Key.Y));
                vals[0] = kvp.Value;
                uvValues.Add(new ValueAtPoint(vals));
            }

            FieldDomainPointsByUV pnts = new FieldDomainPointsByUV(uvPts);
            FieldValues fVals = new FieldValues(uvValues);

            sfm.UpdateSpatialFieldPrimitive(_sfp_index, pnts, fVals, _schemaId);
        }

 

Tags (1)
2 REPLIES 2
Message 2 of 3
jeremy_tammik
in reply to: phague

Normally, the UV coordinates depend on the face. Simply converting the XYZ X and Y values directly to UV will not work.

  

To convert a XYZ point to the face UV space, you can use the Project method to project it from global 3D space onto the face 2D:

  

https://www.revitapidocs.com/2023/4bee3e30-74fa-3103-c2f4-d07618fbcedf.htm

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 3 of 3
phague
in reply to: jeremy_tammik

Jeremy,

Thank you. That was just what I needed!

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

Post to forums  

Autodesk Design & Make Report