ModelicaSpecification icon indicating copy to clipboard operation
ModelicaSpecification copied to clipboard

Clarify restrictions on fill patterns.

Open HansOlsson opened this issue 4 weeks ago • 31 comments

Closes #1826

HansOlsson avatar Dec 04 '25 08:12 HansOlsson

The best way to proceed might then be to let the tools that have implemented this describe what they do, so that we can see if the implementations have something in common that we can agree upon?

henrikt-ma avatar Dec 04 '25 11:12 henrikt-ma

We have libraries using these fill patterns on polygons. Why would we restrict/remove something that clearly is useful?

d-hedberg avatar Dec 04 '25 12:12 d-hedberg

The best way to proceed might then be to let the tools that have implemented this describe what they do, so that we can see if the implementations have something in common that we can agree upon?

Ok, making a table based on what I assume:

Pattern Ellipse Rectangle Polygon
Solid etc Yes Yes Yes
HorizontalCylinder Dymola,WSM Dymola,WSM WSM
VerticalCylinder Dymola,WSM Dymola,WSM WSM
Sphere Dymola, Dymola, ?

It seems that the only potentially missing feature is spherical gradient for polygons, and it shouldn't be that difficult to support. So the simplest is to just don't change anything.

HansOlsson avatar Dec 04 '25 12:12 HansOlsson

System Modeler also supports sphere fills on Polygons.

d-hedberg avatar Dec 04 '25 12:12 d-hedberg

System Modeler image

d-hedberg avatar Dec 04 '25 12:12 d-hedberg

For sphere fill on polygons, System Modeler does: // The center point is the center point of the polygon's bounding box. // The radius is the distance from the polygon's center point to the vertex farthest away.

d-hedberg avatar Dec 04 '25 12:12 d-hedberg

Just wondering, but wouldn't it make sense if the center and radius of the Sphere gradient were defined in such a way that they transform consistently with the rest of the shape under Euclidean transformations? (A spherical gradient with circular level curves can't transform naturally when skewing or scaling differently in different directions.)

If the center is defined so that it transforms naturally with the shape, it is natural to define the radius as the distance from the center to the controlling point furtherest away (simpler math compared to the distance to the point furtherest away on the curve delimiting the shape).

One simple definition of the center is to use the origin in the local coordinates of the shape. This also has the advantage that the user can select where to put the center.

Another option is to define the center as the center of mass of the polygon with vertices at the controlling points (simpler math compared to the center of mass of the curve delimiting the shape). For @d-hedberg's example of an equilateral triangle in https://github.com/modelica/ModelicaSpecification/pull/3789#issuecomment-3612076970, this would result in the same color at all three corners of the triangle, no matter how it is rotated.

henrikt-ma avatar Dec 05 '25 19:12 henrikt-ma

Please don't take https://github.com/modelica/ModelicaSpecification/pull/3789#issuecomment-3618298772 as a concrete proposal; it has several drawbacks:

  • The idea of using the local origin will break appearance badly for existing use if the origin isn't near "the center".
  • There are many more centers of mass that could be sensible choices, even without adding the more numerically demanding ones to the list, so picking one of them would become an arbitrary design decision.
  • It would be disruptive for System Modeler users.
  • It would require implementation effort for Wolfram to comply with the specification.

One thing that I believe might help us reach agreement would be to introduce a gradientCenter attribute in FilledShape, which would be optional for Rectangle and Ellipse, defaulting to being at the obvious center of the shape. For Polygon it should be non-optional, but with a deprecated semantics of tool-specific behavior when being unspecified.

However, when thinking more about how to define the "gradient length", I realized that it wasn't clear to me how Sphere should be applied even to a non-circular Ellipse. Should it be A or B below? ellipses

Interpretations:

  • A: Paint a circle as if it were a sphere, and then transform the painted object.
  • B: Paint a big circle as if it were a sphere, then transform the boundary and use it to clip the painted circle.

henrikt-ma avatar Dec 07 '25 23:12 henrikt-ma

Please don't take #3789 (comment) as a concrete proposal; it has several drawbacks:

  • The idea of using the local origin will break appearance badly for existing use if the origin isn't near "the center".
  • There are many more centers of mass that could be sensible choices, even without adding the more numerically demanding ones to the list, so picking one of them would become an arbitrary design decision.
  • It would be disruptive for System Modeler users.
  • It would require implementation effort for Wolfram to comply with the specification.

One thing that I believe might help us reach agreement would be to introduce a gradientCenter attribute in FilledShape, which would be optional for Rectangle and Ellipse, defaulting to being at the obvious center of the shape. For Polygon it should be non-optional, but with a deprecated semantics of tool-specific behavior when being unspecified.

However, when thinking more about how to define the "gradient length", I realized that it wasn't clear to me how Sphere should be applied even to a non-circular Ellipse. Should it be A or B below? ellipses

Yes, sphere-gradient and non-circles (including ellipses) is a problem. I say that "A", i.e., sphere-gradient on a circle stretched to make it an ellipse is the most intuitive - but I have no idea how to easily generalize it to polygons.

HansOlsson avatar Dec 08 '25 07:12 HansOlsson

If we are not sure exactly what to do, it might also help to take a look at SVG. A Modelica Sphere gradient would most closely resemble a <radialGradient> fill in SVG (a tool can insert more <step> elements to better approximate the reflection on a sphere):

  • https://www.w3schools.com/graphics/svg_grad_radial.asp
  • https://www.w3.org/TR/SVG11/pservers.html#RadialGradients

(SVG makes the interpretation A in https://github.com/modelica/ModelicaSpecification/pull/3789#issuecomment-3623711621.)

henrikt-ma avatar Dec 08 '25 07:12 henrikt-ma

Yes, sphere-gradient and non-circles (including ellipses) is a problem. I say that "A", i.e., sphere-gradient on a circle stretched to make it an ellipse is the most intuitive - but I have no idea how to easily generalize it to polygons.

I would say that you need something equivalent to an ellipse to define the gradient, and then you can clip it to any desired shape. For a Rectangle there aren't that many candidates for how to define the default ellipse (inscribed or circumscribed), but for a Polygon it gets nasty to define a default.

However, note that even if defining a default for the specification is a nasty problem, making the Sphere gradient ellipse a part of FilledShape (only required when using Sphere on a Polygon, and with deprecated semantics for not specifying it) means that we leave it to tools to just throw out a not too crazy ellipse when Sphere fill is selected for a Polygon, and then it is up to the user to adjust the ellipse to taste.

Edit: Note that in comparison to SVG, SVG has a generic gradientTransform attribute, meaning that their definition of a radial gradient can concentrate on defining the gradient applied to a circular shape. It is because we don't have anything corresponding to gradientTransform in Modelica that we need a "gradient outermost ellipse", and not just a "gradient outermost circle" as in SVG.

henrikt-ma avatar Dec 08 '25 08:12 henrikt-ma

There are libraries out there that use this, and it is clearly useful, so removing this feature is not reasonable.

Do you also have an easy way to find applications of Sphere to Rectangle or Polygon?

henrikt-ma avatar Dec 08 '25 08:12 henrikt-ma

Looking more I realize that there are two additional issues with gradients, with relevant icons in MSL:

  • Modelica.Mechanics.MultiBody.Parts.Body rectangles with rounded corners, I assume we just base the gradient on the unrounded case?
  • Modelica.Mechanics.Rotational.Sources.Accelerate forgetting to set LinePattern.None (a lot of cases) as the default is Solid, which would cause problems. I made a PR for improving that: https://github.com/modelica/ModelicaStandardLibrary/pull/4711

HansOlsson avatar Dec 08 '25 08:12 HansOlsson

There are libraries out there that use this, and it is clearly useful, so removing this feature is not reasonable.

Do you also have an easy way to find applications of Sphere to Rectangle or Polygon?

For Rectangle it is used for Modelica.Mechanics.Translational.Components.Mass, looking like this in Dymola 2026x:

Mass

Nice effect, but unfortunately without any clear relation to radial gradient - more like a combined vertical and horizontal gradient.

HansOlsson avatar Dec 08 '25 09:12 HansOlsson

Nice effect, but unfortunately without any clear relation to radial gradient - more like a combined vertical and horizontal gradient.

Yes. First I thought you had implemented the generalization to draw rays with a color gradient, each ray starting at the center and ending at the periphery, but then I saw the lighter "X" pattern which proved me wrong.

henrikt-ma avatar Dec 08 '25 09:12 henrikt-ma

  • Modelica.Mechanics.MultiBody.Parts.Body rectangles with rounded corners, I assume we just base the gradient on the unrounded case?

Sounds very reasonable to me.

henrikt-ma avatar Dec 08 '25 10:12 henrikt-ma

Can you made an example model of all cases which other tools can load and show how they render patterns.

This is how OpenModelica renders the example given here https://github.com/modelica/ModelicaSpecification/pull/3789#pullrequestreview-3539138623 image

For Modelica.Mechanics.MultiBody.Parts.Body,

image

For Modelica.Mechanics.Translational.Components.Mass

image

adeas31 avatar Dec 08 '25 13:12 adeas31

This is more or less the model I used in https://github.com/modelica/ModelicaSpecification/pull/3789#issuecomment-3623711621:

model EllipsePainting
  model A
    annotation(
      Diagram(
        coordinateSystem(extent = {{-150, -90}, {150, 90}})
      ),
      Icon(
        coordinateSystem(extent = {{-100, -100}, {100, 100}}),
        graphics = {
          Ellipse(fillColor = {255, 0, 0}, fillPattern = FillPattern.Sphere, extent = {{-100, -100}, {100, 100}})
        }
      )
    );
  end A;

  A a1 annotation(
      Placement(transformation(origin = {40, 80}, extent = {{-20, -60}, {20, 60}}))
    );
  annotation(
    preferredView = "diagram",
    Diagram(
      coordinateSystem(extent = {{10, 10}, {130, 150}}),
      graphics = {
        Ellipse(origin = {100, 80}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Sphere, extent = {{-20, -60}, {20, 60}})
      }
    )
  );
end EllipsePainting;

henrikt-ma avatar Dec 08 '25 14:12 henrikt-ma

This is more or less the model I used in #3789 (comment):

model EllipsePainting
  model A
    annotation(
      Diagram(
        coordinateSystem(extent = {{-150, -90}, {150, 90}})
      ),
      Icon(
        coordinateSystem(extent = {{-100, -100}, {100, 100}}),
        graphics = {
          Ellipse(fillColor = {255, 0, 0}, fillPattern = FillPattern.Sphere, extent = {{-100, -100}, {100, 100}})
        }
      )
    );
  end A;

  A a1 annotation(
      Placement(transformation(origin = {40, 80}, extent = {{-20, -60}, {20, 60}}))
    );
  annotation(
    preferredView = "diagram",
    Diagram(
      coordinateSystem(extent = {{10, 10}, {130, 150}}),
      graphics = {
        Ellipse(origin = {100, 80}, fillColor = {255, 0, 0}, fillPattern = FillPattern.Sphere, extent = {{-20, -60}, {20, 60}})
      }
    )
  );
end EllipsePainting;

This one gives,

image

adeas31 avatar Dec 08 '25 14:12 adeas31

This is more or less the model I used in #3789 (comment):

Dymola 2026x generates the following (which I like):

EllipsePainting

HansOlsson avatar Dec 08 '25 15:12 HansOlsson

And for Modelica.Mechanics.MultiBody.Parts.Body Dymola 2026x generates (which I also like, except I don't know if there's an optical illusion or something odd at the rounded corners):

Body

HansOlsson avatar Dec 08 '25 15:12 HansOlsson

And for Modelica.Mechanics.MultiBody.Parts.Body Dymola 2026x generates (which I also like, except I don't know if there's an optical illusion or something odd at the rounded corners):

I zoomed in, and it is not an optical illusion; the level curves of equal color are bent near the left end of the cylinder. Makes you wonder what is going on behind that gray connector… Any similar effects on a rectangle without rounded corners?

henrikt-ma avatar Dec 08 '25 16:12 henrikt-ma

And for Modelica.Mechanics.MultiBody.Parts.Body Dymola 2026x generates (which I also like, except I don't know if there's an optical illusion or something odd at the rounded corners):

I zoomed in, and it is not an optical illusion; the level curves of equal color are bent near the left end of the cylinder. Makes you wonder what is going on behind that gray connector… Any similar effects on a rectangle without rounded corners?

There shouldn't be. I know what could cause it specifically for rounded corners, but didn't investigate it enough.

HansOlsson avatar Dec 08 '25 16:12 HansOlsson

With so much variation between tools in the looks of these gradients, maybe we better just conclude that the specification failed pretty badly this time by introducing all these underspecified ways of filling shapes. Instead of seeking agreement about how extend and clarify the specification, isn't it better that we make a plan to deprecate all these underspecified fills, and instead spend our efforts on strengthening the support for SVG?

For example, these are all things that would seem more worthwhile standardizing:

  • Allow inline SVG images, instead of the current limitation to Bitmap with an external file.
  • Define variable replacement for SVG <text> elements.
  • Define how to use Modelica expressions in SVG attributes.
  • Define how to do DynamicSelect in SVG.
  • Allow the entire Icon.graphics or Diagram.graphics to be a single SVG document.

henrikt-ma avatar Dec 08 '25 20:12 henrikt-ma

I find the graphic primitives provided by Modelica sufficient for creating the graphics needed for icons (including the possibility to use SVG images in Bitmap primitives). Seems a bit too drastic to deprecate something that has been around pretty much since the birth of Modelica and replace it with something new that doesn't bring that much more to the table. All tools would still have to support the original primitives for many years to come as many libraries depend on these, so tools would become more complex not only for the developers of the tools but also for the users. Obviously there has been slight variations in the fill patterns in tools for years and I don't find this to be a critical issue that would justify deprecating the graphics annotations.

d-hedberg avatar Dec 09 '25 07:12 d-hedberg

And preliminarily for Dymola the model from https://github.com/modelica/ModelicaSpecification/pull/3789#pullrequestreview-3539138623 gives:

Package

HansOlsson avatar Dec 09 '25 10:12 HansOlsson

I have now tried to clarify the gradient instead of restricting it. More work remain, but I think it is a step forward.

HansOlsson avatar Dec 15 '25 09:12 HansOlsson

I have tried to reformulate based on this, but without introducing "band".

HansOlsson avatar Dec 16 '25 16:12 HansOlsson

I have tried to reformulate based on this, but without introducing "band".

Sure, that seems workable.

henrikt-ma avatar Dec 17 '25 08:12 henrikt-ma

Sounds good to me, but wouldn't it make sense to include some visual examples complementing the text? It would decrease the risk of different (mis)interpretations of the text.

d-hedberg avatar Dec 17 '25 11:12 d-hedberg