How to set compound structure for two different layers if I used 2 different categories of material for wall structure , using revit api - revit-api

I am trying to create a wall with 2 layers and each layer materials are different. When I try to set the CompoundStructure for the wall I am getting an exception that CompoundStructure is not valid.
CompoundStructure cStructure = CompoundStructure.CreateSimpleCompoundStructure(clayer);
wallType.SetCompoundStructure(cStructure);
Can anyone tell me how I can create compound structure for layers with different materials?

First of all, solve your task manually through the end user interface and verify that it works at all.
Then, use RevitLookup and other database exploration tools to examine the results in the BIM elements, their properties and relationships.
Once you have done that, you will have a good idea how to address the task programmatically – and have confidence that it will work as expected:
How to research to find a Revit API solution
Intimate Revit database exploration with the Python Shell

newWallMaterial = wallMaterial.Duplicate("newCreatedMaterial");
newWallmaterial2 = wallMaterial.Duplicate("NewCreatedMAterial2");
//roofMaterial3 = roofMaterial2.Duplicate("NewCreatedMAterial3");
bool usr = newWallMaterial.UseRenderAppearanceForShading;
//newWallMaterial.Color = BuiltInTypeParam.materialCol;
foreach (Layers layer in layers)
{
if (layer.layerId == 0)
{
c = new CompoundStructureLayer(layer.width, layer.materialAssignement, newWallMaterial.Id);
newWallMaterial.Color = color;
clayer.Add(c);
}
if (layer.layerId == 1)
{
c1 = new CompoundStructureLayer(layer.width, layer.materialAssignement, newWallmaterial2.Id);
newWallmaterial2.Color = color;
clayer.Add(c1);
}

Related

List all "unique paths" to a node

I have a representation of a process trough something that is very much like a DAG (Directed Acyclic Graph). This graph is represented with an adjacency table, but not like a "regular" adjacency table, there are few differences:
Each entry in the table is a list of lists,
Each "inner" list states the predecessor nodes required.
The idea for this data structure is to hold requirements of steps within a process. So, for example:
P = {1:[[]], 2:[[1]], 3:[[2]], 4:[[3]], 5:[[2]], 6:[[]], 7: [[4,6],[8,5]], 8:[[]]}
For process P, step 1 doesn't require any predecessor, step requires step 1,..., step 6 also doesn't require any predecessor, step 7 requires steps (4 and 6) OR (8 and 5).
Each step has a state (some ID reference) that determines if the next step can be executed or not, or if the process can be terminated or not.
In the example above, I would not be able to execute step 2 if step 1 didn't fulfill some specific condition regarding the state the same for step 5, which requires step 2 with state=something specific. And for step 7, the only way to execute it, would be if step 4&6 OR 5&8 have their corresponding state=something specific.
What I need is a way to get all the unique paths that lead to a certain step, so later I can check against this paths if the conditions are met. For step 7 it would be :
paths = [[1,2,3,4,6],[1,2,5,8]]
I've checked:
Python get all paths from graph
How to implement the search for all paths inside a directed graph in JavaScript? (reversing this??)
Depth first search list paths to all end nodes
How to find the nodes that leads to node A without traversing all the graph (directed graph)
Most of the information around points to some sort of modified DFS or some kind of enhanced Dijkstra. For what I've checked and tested none of the above gives me what I need which is a list of all "unique paths" that lead to a node that may be reached from "different paths".
The question is not language specific, so any example in any language would be appreciated :)
EDIT: 04/01/22
Further clarifications:
The steps are one way, meaning that node 1 is connected to step 2 by a distance of 1, to step 3 a distance of 2, and so on. But step/node 1 is not conntected with 6 or 8.
All graphs have a unique starting point and ending point. In the example 1 and 7.
Yes, node 5 should be connected to node 7. Img updated.
The number of nodes will always be <100.
How big is your graph? What is your performance requirement?
For a small graph like your example, Dijsktra is almost instant. So you do not need to store all the paths.
Set cost of all links to 1
Set cost of links that lead to nodes that are NOT in the required state to 10^10
Run Dijkstra to find shortest path from source to destination through nodes in required state.
I think I've managed to get what I needed, nevertheless I think the answer is overly complex.
Function to populate a tracker object with all the possible paths.
const tracker = {};
function getPaths (step, branchRef) {
const currentStepRequires = getStepRequires(step); // func that gets the array of arrays of current step
const oldBranchRef = branchRef;
const hasBranches = currentStepRequires.length > 1;
for (const branch of currentStepRequires) {
if (branch.length === 0) {
return;
}
if (!hasBranches && !branchRef) {
tracker[branch] = [];
}
if (!branchRef) branchRef = branch;
if (hasBranches) {
if (oldBranchRef && oldBranchRef !== branchRef) {
tracker[branch] = [...tracker[oldBranchRef]];
}
else if (tracker[branchRef]) {
tracker[branch] = [...tracker[branchRef]];
branchRef = branch;
}
else {
tracker[branch] = [];
}
}
for (const step of branch) {
tracker[branchRef].push(step);
getPaths(step, branchRef);
}
if (hasBranches) branchRef = '';
}
}
After the tracker object has been populated I need to remove the paths that are contained within the other paths.
I'm using lodash here to simplify the filtering, checking and adding the paths
const paths = [];
_.forEach(_.sortBy(tracker, path => path.length * -1), branch => {
const isSubpath = _.some(paths, path => _.isEqual(branch, _.intersection(path, branch)));
if (!isSubpath) {
paths.push(branch);
}
});
For the example above, this returns the following:
[[4,3,2,1,6], [8,5,2,1]]
I've also tested with more "branching", like example:
P = {1:[[]], 2:[[1]], 3:[[2]], 4:[[3]], 5:[[2]], 6:[[]], 7: [[4,6],[8],[5]], 8:[[6],[3]]}
Which returns:
[[4,3,2,1,6],[8,6],[8,3,2,1],[5,2,1]]
For now its working, but....as I said, I think its more complicated than it needs to be. So, any improvements are welcome.

How does one access an Extension to a table in Acumatica Business Logic

Apologies if this question has been answered elsewhere, I have had trouble finding any resources on this.
The scenario is this. I have created a custom field in the Tax Preferences screen called Usrapikey.
This value holds an api key for a call that gets done in some custom business logic.
The custom business logic however occurs on the Taxes screen.
So within the event handler I need to access that API key value from the other screen. I have tried instantiating graphs and using linq and bql but to no avail.
below is what I have currently and my error is: No overload for method 'GetExtension' takes 1 arguments
If I am going about this the wrong way please let me know if there is a more civilized way to do this
protected virtual void _(Events.FieldUpdated<TaxRev, TaxRev.startDate> e)
{
var setup = PXGraph.CreateInstance<TXSetupMaint>();
var TXSetupEX = setup.GetExtension<PX.Objects.TX.TXSetupExt>(setup);
var rateObj = GetValues(e.Row.TaxID, TXSetupEX.Usrapikey);
decimal rate;
var tryRate = (Decimal.TryParse(rateObj.rate.combined_rate, out rate));
row.TaxRate = (decimal)rate * (decimal)100;
row.TaxBucketID = 1;
}
Many Thanks!
Well, acumatica support got back. It seems if you want to access the base page use:
TXSetup txsetup = PXSetup<TXSetup>.Select(Base);
To get the extension use:
TXSetupExt rowExt = PXCache<TXSetup>.GetExtension<TXSetupExt>(txsetup);
Then you can access the extension fields like so:
var foo = rowExt.Usrfield;

ILOG CPLEX / OPL dynamic Excel sheet referencing

I'm trying to dynamically reference Excel sheets or tables within the .dat for a Mixed Integer Problem in Vehicle Routing that I'm trying to solve in CPLEX (OPL).
The setup is a: .mod = model, .dat = data and a MS Excel spreadsheet
I have a 2 dimensional array with customer demand data = Excel range (for coding convenience I did not format the excel data as a table yet)
The decision variable in .mod looks like this:
dvar boolean x[vertices][vertices][scenarios]
in .dat:
vertices from SheetRead (data, "Table!vertices");
and
scenarios from SheetRead (data, "dont know how to yet"); this might not be needed
without the scenario Index everything is fine.
But as the demand for the customers changes in this model I'd like to include this via changing the data base reference.
Now what I'd like to do is one of 2 things:
Either:
Change the spreadsheet in Excel so that depending on the scenario I get something like that in .dat:
scenario = 1:
vertices from SheetRead (data, "table-scenario-1!vertices");
scenario = 2:
vertices from SheetRead (data, "table-scenario-2!vertices");
so changing the spreadsheet for new base data,
or:
Change the range within the same spreadsheet:
scenario = 1:
vertices from SheetRead (data, "table!vertices-1");
scenario = 2:
vertices from SheetRead (data, "table!vertices-2");
either way would be fine.
Knowing how 3D Tables in Excel are created using multiple spreadsheets with 2D Tables grouped, the more natural approach seems to be, to have vertices always reference the same range in every Excel spreadsheet while depending on the scenario the spreadsheet/page is switched, but I just don't know how to.
Thanks for the advice.
Unfortunately, the arguments to SheetConnection must be a string literal or an Id (see the OPL grammar in the user manual here). And similarly for SheetRead. This means, you cannot have dynamic sources for a sheet connection.
As we discussed in the comments, one option is to add an additional index to all data: the scenario. Then always read the data for all scenarios and in the .mod file select what you want to actually use.
at https://www.ibm.com/developerworks/community/forums/html/topic?id=5af4d332-2a97-4250-bc06-76595eef1ab0&ps=25 I shared an example where you can set a dynamic name for the Excel file. The same way you could have a dynamic range, the trick is to use flow control.
sub.mod
float maxOfx = 2;
string fileName=...;
dvar float x;
maximize x;
subject to {
x<=maxOfx;
}
execute
{
writeln("filename= ",fileName);
}
and then the main model is
main {
var source = new IloOplModelSource("sub.mod");
var cplex = new IloCplex();
var def = new IloOplModelDefinition(source);
var opl = new IloOplModel(def,cplex);
for(var k=11;k<=20;k++)
{
var opl = new IloOplModel(def,cplex);
var data2= new IloOplDataElements();
data2.fileName="file"+k;
opl.addDataSource(data2);
opl.generate();
if (cplex.solve()) {
writeln("OBJ = " + cplex.getObjValue());
} else {
writeln("No solution");
}
opl.postProcess();
opl.end();
}
}

Create Dimensions from edge of wall, to sides of openings, to other edge of wall

I've been struggling with this issue off and on for the better part of a year.
As the title says, i wish to dimension from one side of a wall, to both sides of openings (door openings), then terminate at the other end of the wall (vertically and horizontally). I also wish to dimension to all families hosted in the wall, but i have been able to accomplish this using ScottWilson's voodo magic helper class. Found Here: http://thebuildingcoder.typepad.com/blog/2016/04/stable-reference-string-magic-voodoo.html
foreach (ElementId ele in selSet) {
FamilyInstance fi = doc.GetElement(ele) as FamilyInstance;
Reference reference = ScottWilsonVoodooMagic.GetSpecialFamilyReference(fi,ScottWilsonVoodooMagic.SpecialReferenceType.CenterLR,doc);
refs.Append(reference);
pts[i] = ( fi.Location as LocationPoint ).Point;
i++;
}
XYZ offset = new XYZ(0,0,4);
Line line = Line.CreateBound( pts[0]+offset, pts[selSet.Count - 1]+offset );
using( Transaction t = new Transaction( doc ) )
{
t.Start( "dimension embeds" );
Dimension dim = doc.Create.NewDimension(doc.ActiveView, line, refs );
t.Commit();
}
The problem lies in determining the appropriate stable references to the wall faces. I am able to find all faces on a wall, but this gives me 100+ faces to sort through.
If anyone can help me it would be greatly appreciated!
Side note: The closest of gotten is using a casting a ray trace through my panel, then using a reference intersector method to determine references. But i'm really struggling with implementation: http://thebuildingcoder.typepad.com/blog/2015/12/retrieving-wall-openings-and-sorting-points.html
These two posts should provide more than enough to solve all your issues:
Dimension walls by iterating their faces
Dimension walls by shooting a ray
Basically, you need to obtain references to the faces or edges that you wish to attach the dimensioning to. These references can be obtained in several ways. Two common and easy approaches are:
Retrieve the element geometry using the option ComputeReferences set to true and extract the specific face required.
Shoot a ray through the model to determine the required element and its face using the 2017
ReferenceIntersector Class.

Spark IntArrayParm in JAVA

I am trying to test a number of multilayer perception network architectures. So, I am training a model via a crossvalidation using different params. However, I fail to set up layer param using JAVA. Not sure how this is done, but none of the following work:
int[] layers1 = new int[]{10,1,3,2};
IntArrayParam p = new IntArrayParam(null, "name", "doc");
p.w(layers1);
int[] layers2 = new int[]{10,1,3,2};
IntArrayParam p2 = new IntArrayParam(null, "name", "doc");
p2.w(layers2);
builder.addGrid(mlpc.layers(), JavaConverters.asScalaIterableConverter(Arrays.asList(p,1)).asScala());
Sending a list of arrays (or a multidimensional array):
builder.addGrid(mlpc.layers(), JavaConverters.asScalaIterableConverter(Arrays.asList(1,2,2), Arrays.asList(1,2,2)).asScala());
I am not sure how this i suppose to be done in JAVA, and was not able to find any examples. Any ideas appreciated.
Best,
Ilija
After some research got it, just in case anyone gets stuck using IntArrayParam on Java here is an example:
//build network parameters grid
int[] layers1=new int[]{17,8,4,26};
int[] layers2=new int[]{17,12,8,26};
//use scala collections converters to get a Scala Iterable of Int[]
scala.collection.Iterable<int[]> iter= JavaConverters.iterableAsScalaIterableConverter(Arrays.asList(layers1, layers2)).asScala();
Hope that helps!

Resources