Null values in arraylist break lines in Androidplot - androidplot

I plot the graph with androidplot. calling values from database has null values in the arraylist. The x-axis values have a two corresponding y-values. The null y-value doesn't plot (which perfect) but breaks the line into two. I want the line to join leaving the null values out (point {5,5} should join point {7,8} without a break)
Number[] xAlertseries1={3,4,5,6,7,8,9};
Number[] yAlertseries2={4,10,5,null,8,9,10};
Number[] yActionseries={4,10,11,13,14,15,16};
XYSeries alertseries = new SimpleXYSeries(Arrays.asList(xAlertseries1), Arrays.asList(yAlertseries2),"ALERT");
XYSeries actionseries = new SimpleXYSeries(Arrays.asList(xAlertseries1), Arrays.asList(yActionseries),"ACTION");
labprogplotter.addSeries(alertseries, actionalertformat);
labprogplotter.addSeries(actionseries, actionalertformat);
labprogplotter.redraw();

It's funny i had to answer my own question. Yes, Bert
Number[] xAlertseries1={3,4,5,6,7,8,9};
//created a new xActionseries so that all have their own x-values
Number[] xActionseries={3,4,5,6,7,8,9};
Number[] yAlertseries2={4,10,5,null,8,9,10};
Number[] yActionseries={4,10,11,13,14,15,16};
//iterated to remove null values in yAlertseries2 and its corresponding value in its x-values
for(int i=0;i<yAlertseries2.size();i++)
{ if(yAlertseries2.get(i)==null)
{
yAlertseries2.remove(i);
xAlertseries1.remove(i);
i--;
} }
XYSeries alertseries = new SimpleXYSeries(Arrays.asList(xAlertseries1), Arrays.asList(yAlertseries2),"ALERT");
XYSeries actionseries = new SimpleXYSeries(Arrays.asList(xActionseries), Arrays.asList(yActionseries),"ACTION");
labprogplotter.addSeries(alertseries, actionalertformat);
labprogplotter.addSeries(actionseries, actionalertformat);
labprogplotter.redraw()

Related

Revit API. How can I get bounding box for several elements?

I need to find an outline for many elements (>100'000 items). Target elements come from a FilteredElementCollector. As usual I'm looking for the fastest possible way.
For now I tried to iterate over all elements to get its BoudingBox.Min and BoudingBox.Max and find out minX, minY, minZ, maxX, maxY, maxZ. It works pretty accurate but takes too much time.
The problem is described above is a part of a bigger one.
I need to find all the intersections of ducts, pipes and other curve-based elements from a link model with walls, ceilings, columns, etc. in the general model and then place openings in a intersection.
I tried to use a combination of ElementIntersectElement filter and IntersectSolidAndCurve method to find a part of curve inside element.
First with an ElementIntersectElement I tried to reduce a collection for further use of IntersectSolidAndCurve .IntersectSolidAndCurve takes two argument: solid and curve and have to work in two nested one in the other loops. So, it takes for 54000 walls (after filtering) and 18000 pipes in my case 972'000'000 operation.
With the number of operations 10 ^ 5, the algorithm shows an acceptable time.
I decided to reduce the number of elements by dividing the search areas by levels. This works well for high-rise buildings, but still bad for extended low structures. I decided to divide the building by length, but I did not find a method that finds boundaries for several elements (the whole building).
I seem to go in a wrong way. Is there are right way to make it with revit api instrument
To find boundaries we can take advantage of the binary search idea.
The difference from the classic binary search algorithm is there is no an array, and we should find two number instead of a one.
Elements in Geometry space could be presented as a 3-dimensional sorted array of XYZ points.
Revit api provides excellent Quick Filter: BoundingBoxIntersectsFilter that takes an instance of an Outline
So, let’s define an area that includes all the elements for which we want to find the boundaries. For my case, for example 500 meters, and create min and max point for the initial outline
double b = 500000 / 304.8;
XYZ min = new XYZ(-b, -b, -b);
XYZ max = new XYZ(b, b, b);
Below is an implementation for one direction, however, you can easily use it for three directions by calling and feeding the result of the previous iteration to the input
double precision = 10e-6 / 304.8;
var bb = new BinaryUpperLowerBoundsSearch(doc, precision);
XYZ[] rx = bb.GetBoundaries(min, max, elems, BinaryUpperLowerBoundsSearch.Direction.X);
rx = bb.GetBoundaries(rx[0], rx[1], elems, BinaryUpperLowerBoundsSearch.Direction.Y);
rx = bb.GetBoundaries(rx[0], rx[1], elems, BinaryUpperLowerBoundsSearch.Direction.Z);
The GetBoundaries method returns two XYZ points: lower and upper, which change only in the target direction, the other two dimensions remain unchanged
public class BinaryUpperLowerBoundsSearch
{
private Document doc;
private double tolerance;
private XYZ min;
private XYZ max;
private XYZ direction;
public BinaryUpperLowerBoundsSearch(Document document, double precision)
{
doc = document;
this.tolerance = precision;
}
public enum Direction
{
X,
Y,
Z
}
/// <summary>
/// Searches for an area that completely includes all elements within a given precision.
/// The minimum and maximum points are used for the initial assessment.
/// The outline must contain all elements.
/// </summary>
/// <param name="minPoint">The minimum point of the BoundBox used for the first approximation.</param>
/// <param name="maxPoint">The maximum point of the BoundBox used for the first approximation.</param>
/// <param name="elements">Set of elements</param>
/// <param name="axe">The direction along which the boundaries will be searched</param>
/// <returns>Returns two points: first is the lower bound, second is the upper bound</returns>
public XYZ[] GetBoundaries(XYZ minPoint, XYZ maxPoint, ICollection<ElementId> elements, Direction axe)
{
// Since Outline is not derived from an Element class there
// is no possibility to apply transformation, so
// we have use as a possible directions only three vectors of basis
switch (axe)
{
case Direction.X:
direction = XYZ.BasisX;
break;
case Direction.Y:
direction = XYZ.BasisY;
break;
case Direction.Z:
direction = XYZ.BasisZ;
break;
default:
break;
}
// Get the lower and upper bounds as a projection on a direction vector
// Projection is an extention method
double lowerBound = minPoint.Projection(direction);
double upperBound = maxPoint.Projection(direction);
// Set the boundary points in the plane perpendicular to the direction vector.
// These points are needed to create BoundingBoxIntersectsFilter when IsContainsElements calls.
min = minPoint - lowerBound * direction;
max = maxPoint - upperBound * direction;
double[] res = UpperLower(lowerBound, upperBound, elements);
return new XYZ[2]
{
res[0] * direction + min,
res[1] * direction + max,
};
}
/// <summary>
/// Check if there are any elements contains in the segment [lower, upper]
/// </summary>
/// <returns>True if any elements are in the segment</returns>
private ICollection<ElementId> IsContainsElements(double lower, double upper, ICollection<ElementId> ids)
{
var outline = new Outline(min + direction * lower, max + direction * upper);
return new FilteredElementCollector(doc, ids)
.WhereElementIsNotElementType()
.WherePasses(new BoundingBoxIntersectsFilter(outline))
.ToElementIds();
}
private double[] UpperLower(double lower, double upper, ICollection<ElementId> ids)
{
// Get the Midpoint for segment mid = lower + 0.5 * (upper - lower)
var mid = Midpoint(lower, upper);
// Сheck if the first segment contains elements
ICollection<ElementId> idsFirst = IsContainsElements(lower, mid, ids);
bool first = idsFirst.Any();
// Сheck if the second segment contains elements
ICollection<ElementId> idsSecond = IsContainsElements(mid, upper, ids);
bool second = idsSecond.Any();
// If elements are in both segments
// then the first segment contains the lower border
// and the second contains the upper
// ---------**|***--------
if (first && second)
{
return new double[2]
{
Lower(lower, mid, idsFirst),
Upper(mid, upper, idsSecond),
};
}
// If elements are only in the first segment it contains both borders.
// We recursively call the method UpperLower until
// the lower border turn out in the first segment and
// the upper border is in the second
// ---*****---|-----------
else if (first && !second)
return UpperLower(lower, mid, idsFirst);
// Do the same with the second segment
// -----------|---*****---
else if (!first && second)
return UpperLower(mid, upper, idsSecond);
// Elements are out of the segment
// ** -----------|----------- **
else
throw new ArgumentException("Segment is not contains elements. Try to make initial boundaries wider", "lower, upper");
}
/// <summary>
/// Search the lower boundary of a segment containing elements
/// </summary>
/// <returns>Lower boundary</returns>
private double Lower(double lower, double upper, ICollection<ElementId> ids)
{
// If the boundaries are within tolerance return lower bound
if (IsInTolerance(lower, upper))
return lower;
// Get the Midpoint for segment mid = lower + 0.5 * (upper - lower)
var mid = Midpoint(lower, upper);
// Сheck if the segment contains elements
ICollection<ElementId> idsFirst = IsContainsElements(lower, mid, ids);
bool first = idsFirst.Any();
// ---*****---|-----------
if (first)
return Lower(lower, mid, idsFirst);
// -----------|-----***---
else
return Lower(mid, upper, ids);
}
/// <summary>
/// Search the upper boundary of a segment containing elements
/// </summary>
/// <returns>Upper boundary</returns>
private double Upper(double lower, double upper, ICollection<ElementId> ids)
{
// If the boundaries are within tolerance return upper bound
if (IsInTolerance(lower, upper))
return upper;
// Get the Midpoint for segment mid = lower + 0.5 * (upper - lower)
var mid = Midpoint(lower, upper);
// Сheck if the segment contains elements
ICollection<ElementId> idsSecond = IsContainsElements(mid, upper, ids);
bool second = idsSecond.Any();
// -----------|----*****--
if (second)
return Upper(mid, upper, idsSecond);
// ---*****---|-----------
else
return Upper(lower, mid, ids);
}
private double Midpoint(double lower, double upper) => lower + 0.5 * (upper - lower);
private bool IsInTolerance(double lower, double upper) => upper - lower <= tolerance;
}
Projection is an extention method for vector to determine the length of projection one vector for another
public static class PointExt
{
public static double Projection(this XYZ vector, XYZ other) =>
vector.DotProduct(other) / other.GetLength();
}
In principle, what you describe is the proper approach and the only way to do it. However, there may be many possibilities to optimise your code. The Building Coder provides various utility functions that may help. For instance, to determine the bounding box of an entire family. Many more in The Building Coder samples Util module. Search there for "bounding box". I am sure they can be further optimised as well for your case. For instance, you may be able to extract all the X coordinates from all the individual elements' bounding box Max values and use a generic Max function to determine their maximum in one single call instead of comparing them one by one. Benchmark your code to discover optimisation possibilities and analyse their effect on the performance. Please do share your final results for others to learn from. Thank you!

JavaFX distance between two circle and keep updating property

For assignment, I created 2 draggable circle and connect them with line with javaFX.
I need add text which calculate distance between two circle (or length of line) and that text need to keep updating when I drag circles, but that's where I stuck
Circle circle1 = new Circle();
circle1.setCenterX(40);
circle1.setCenterY(40);
circle1.setRadius(10);
Circle circle2 = new Circle();
circle2.setCenterX(120);
circle2.setCenterY(150);
circle2.setRadius(10);
Line line = new Line ();
line.startXProperty().bind(circle1.centerXProperty());
line.startYProperty().bind(circle1.centerYProperty());
line.endXProperty().bind(circle2.centerXProperty());
line.endYProperty().bind(circle2.centerYProperty());
circle1.setOnMousePressed(mousePressEventHandler);
circle1.setOnMouseDragged(mouseDragEventHandler);
circle2.setOnMousePressed(mousePressEventHandler);
circle2.setOnMouseDragged(mouseDragEventHandler);
it's my two circles and line, and I tried
Text distance = new Text();
distance.textProperty().bind(circle1.centerXProperty()-circle2.centerXProperty() . . .);
However, as you know as, I can't normally calculate Property value, and I have no idea how should I do it.
You could create a DoubleProperty
DoubleProperty distanceProperty = new SimpleDoubleProperty();
and a ChangeListener in which you calculate the distance
ChangeListener<Number> changeListener = (observable, oldValue, newValue) -> {
Point2D p1 = new Point2D(circle1.getCenterX(), circle1.getCenterY());
Point2D p2 = new Point2D(circle2.getCenterX(), circle2.getCenterY());
distanceProperty.set(p1.distance(p2));
};
assign the listener
circle1.centerXProperty().addListener( changeListener);
circle1.centerYProperty().addListener( changeListener);
circle2.centerXProperty().addListener( changeListener);
circle2.centerYProperty().addListener( changeListener);
and bind the distanceProperty to the text
Text text = new Text();
text.textProperty().bind(distanceProperty.asString());

Common Elements Sequence

I have two arrays of integer type.
int[] righttarray=new int[] {6,9,8,1,5,3};
int[] leftarray=new int[] {1,3};
Now I have to find out the common elements between these two as well as I need to match common elements indexes. If the indexes are same then its ok, if not then sequence will be maintained from rightarray.
I am getting Common elements by intersect method in C#.
See, element 1 and 3 are common in both the arrays. But in "leftarray" their sequence in 0,1 and in "rightarray" their sequence in 3,5. How to check this is my question. Thanks !!
Help me out doing this.
Ok, try something like:
int[] righttarray = new int[] { 6, 3, 8, 1, 5, 3 };
int[] leftarray = new int[] { 1, 3 };
if (righttarray.Length < leftarray.Length)
{
var result = righttarray.Where((x, i) => righttarray[i] == leftarray[i]);
}
else
{
var result = leftarray.Where((x, i) => leftarray[i] == righttarray[i]);
}
This will give you the number 3, which is in the same index and with the same element number. In your example, the output will be empty, I have changed only to check it ;)

How to transform a list of dictionaries with unique keys to a dictionary whose value is a list?

I have an arbitrary number of dictionaries (which are in a list, already in order) that I wish to outer join. For example, for N = 2:
List<Dictionary<string, int>> lstInput = new List<Dictionary<string, int>>();
Dictionary<string, int> dctTest1 = new Dictionary<string, int>();
Dictionary<string, int> dctTest2 = new Dictionary<string, int>();
dctTest1.Add("ABC", 123);
dctTest2.Add("ABC", 321);
dctTest2.Add("CBA", 321);
lstInput.Add(dctTest1);
lstInput.Add(dctTest2);
Each dictionary already has unique keys.
I wish to transform lstInput into:
Dictionary<string, int[]> dctOutput = new Dictionary<string, int[]>();
where dctOutput looks like:
"ABC": [123, 321]
"CBA": [0, 321]
That is, the set of keys of dctOutput is equal to the union of the set of keys of each dictionary in lstInput; moreover, the *i*th position of each value in dctOutput is equal to the value of the corresponding key in the *i*th dictionary in lstInput, or 0 if there is no corresponding key.
How can I write C# code to accomplish this?
The following should do what you want.
var dctOutput = new Dictionary<string, int[]>();
for (int i = 0; i < lstInput.Count; ++i)
{
var dict = lstInput[i];
foreach (var kvp in dict)
{
int[] values;
if (!dctOutput.TryGetValue(kvp.Key, out values))
{
// Allocating the array zeros the values
values = new int[lstInput.Count];
dctOutput.Add(kvp.Key, values);
}
values[i] = kvp.Value;
}
}
This works because allocating the array initializes all values to 0. So if a previous dictionary didn't have an item with that key, its values will be 0 in that position. If you wanted your sentinel value to be something other than 0, then you would initialize the array with that value after allocating it.

Limit the number of decimal places a user can enter in a GXT grid cell

How can I limit the number of decimal places a user can enter in a GXT grid cell.
I can format the column config via column.setNumberFormat(...) but this just rounds the value to the defined format, e.g. #.##, and the user can enter more than two decimal places.
I would like to limit the input as the users types, so that he/she can only enter a max of two decimal places.
Best,
-- Thomas
You have to implement a custom Validator and add it to the field:
final ColumnConfig config = new ColumnConfig();
config.setNumberFormat(NumberFormat.getFormat("#.##"));
final NumberField field = new NumberField();
field.setPropertyEditorType(Float.class); // needed to convert from String to Number - default ist Double
field.setValidator(new com.extjs.gxt.ui.client.widget.form.Validator(){
public String validate(Field<?> field, String value) {
if(value != null){
final int index = value.indexOf('.');
if(index > -1 && index < value.length() - 3){
return "Maximum number of digits is 2!";
}
}
return null;
}
});
final CellEditor cellEditor = new CellEditor(field);
config.setEditor(cellEditor);

Resources