Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New: Add removal functions #96

Merged
merged 4 commits into from
Mar 18, 2024

Conversation

AlexIchenskiy
Copy link

This PR introduces functions for removing all data, nodes (the same functionality as removing all the data), or edges by reusing existing remove function. It can be used as follows:

orb.data.removeAll();
orb.data.removeAllNodes();
orb.data.removeAllEdges();

@AlexIchenskiy AlexIchenskiy self-assigned this Mar 13, 2024
Copy link
Contributor

@tonilastre tonilastre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks great! There is just one comment on the callback data.

@@ -274,7 +273,35 @@ export class Graph<N extends INodeBase, E extends IEdgeBase> implements IGraph<N
this._applyEdgeOffsets();
this._applyStyle();

this._settings?.onRemoveData?.(data);
if (this._settings && this._settings.onRemoveData) {
this._settings.onRemoveData(data);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a user (internal or external) I would expect to receive in the callback all nodes and edges that have been removed. You are forwarding the data that you've received which doesn't necessarily mean that those have been removed, e.g.

In my graph I have these nodes and edges

  • Nodes: 1, 2, 3
  • Edges A (1-2), B (2-1), C(1-3)

I call remove with nodes = 1, 3, 5 and edges = C, D. But actually nodes 1, 3 will be removed and all edges will be removed (A, B, C). So instead of receiving [1, 3, 5], [C, D] in the callback, I would expect to receive [1, 3], [A, B, C].

// Merge edges removed by removing nodes and by removing edges, ensuring there are no duplicate edge IDs.
removedData.edgeIds = removedData.edgeIds.concat(
removedEdgeIds.filter((edgeId) => removedData.edgeIds.indexOf(edgeId) < 0),
);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the most elegant solution I've found so far, but I'm open to suggestions for any more performant/readable alternatives

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be slow, so I would suggest creating utility function, e.g. dedupArrays that receive a generic array, or multiple arrays and dedups their values - using set or map.

E.g.

dedupArrays([1, 2, 3], [1, 2]) -> [1, 2, 3])
dedupArrays([1, 2, 3], [1, 2], [5, 6]) -> [1, 2, 3, 5, 6])
dedupArrays([1, 2, 3], [1, 2], [5, 6], [], [6, 7]) -> [1, 2, 3, 5, 6, 7])

@@ -474,7 +497,7 @@ export class Graph<N extends INodeBase, E extends IEdgeBase> implements IGraph<N
this._edges.removeMany(removedEdgeIds);
}

private _removeNodes(nodeIds: any[]) {
private _removeNodes(nodeIds: any[]): { nodeIds: any[]; edgeIds: any[] } {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This return type is cool. I would maybe extract it into an interface/type. Also, just for a sake of consistency, I would maybe consider returning the same type on _removeEdges - right now, nodeIds will be always empty, but in the future if we add "removeConnectingNodesfor edges, then the API still holds and can use the returned object with bothnodeIdsandedgeIds`.

// Merge edges removed by removing nodes and by removing edges, ensuring there are no duplicate edge IDs.
removedData.edgeIds = removedData.edgeIds.concat(
removedEdgeIds.filter((edgeId) => removedData.edgeIds.indexOf(edgeId) < 0),
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be slow, so I would suggest creating utility function, e.g. dedupArrays that receive a generic array, or multiple arrays and dedups their values - using set or map.

E.g.

dedupArrays([1, 2, 3], [1, 2]) -> [1, 2, 3])
dedupArrays([1, 2, 3], [1, 2], [5, 6]) -> [1, 2, 3, 5, 6])
dedupArrays([1, 2, 3], [1, 2], [5, 6], [], [6, 7]) -> [1, 2, 3, 5, 6, 7])

Copy link
Contributor

@tonilastre tonilastre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! I've added a small detail for a better code quality.

Comment on lines 282 to 285
const removedData = {
nodeIds: dedupArrays(removedNodesData.nodeIds, removedEdgesData.nodeIds),
edgeIds: dedupArrays(removedNodesData.edgeIds, removedEdgesData.edgeIds),
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small detail here. Whenever you create a new object or an array, always add a type. Types will help you to raise warning if you for example change type in the future.

const removedData: IGraphObjectsIds = {
...

Also, this object should be within if on line 290 because you want to create this object only if settings exists and settings.onRemoveData exists, otherwise time and memory is wasted if settings is not called at all.

@AlexIchenskiy AlexIchenskiy merged commit e9a4632 into new/simulator-fixes Mar 18, 2024
1 check passed
@AlexIchenskiy AlexIchenskiy deleted the new/add-removal-functions branch March 18, 2024 13:30
AlexIchenskiy added a commit that referenced this pull request Mar 27, 2024
* New: Add new simulator (#56)

* New: Add simulator scenarios for manual testing
* New: Refactor simulator (WIP)
* New: Add progress overlay, Update descriptions
* Fix: Introduce new simulator event, Fix main-thread behavior
* Fix: Rearrange class methods based on visibility
* Fix: Improve naming
* Chore(release): 0.2.0
* Fix: Tweak simulator, adjust API slightly
* Fix: Temporarily patch some physics behavior
* Fix: Adjust re-heating parameters
* Fix: tweak physics behavior -> immediately stop sim when disabling
* Chore: Remove the beta from release branches

---------

Co-authored-by: dlozic <davidlozic@gmail.com>

* New: Add zoom and recenter functions (#74)

* New: Add zoom and recenter functions

* Fix: Reduce excessive recentering (#75)

* Fix: Remove excessive recenterings
* Fix: Remove unused code

* Fix: New simulator (#92)

* Chore: Refactor naming

* New: Add new events

* Chore: Refactor code styling

* Docs: Remove unused flags

* Chore: Remove unused simulation functions

* Chore: Refactor view render function calls

* Chore: Add missing tests

* New: Add removal functions (#96)

* New: Add removal functions

* Fix: Add missing callback data

* Chore: Refactor remove return values

* Chore: Refactor remove function type usage

* Fix: Default settings for node placement (#98)

* New: Add properties setters and getters (#93)

* New: Add node properties setters

* New: Add edge properties setters

* New: Add properties getters

* New: Add patch for nodes and edges

* Fix: Make getters return copies

* Fix: Edge factory listeners copying

* Fix: Jest outdated tests

* Fix: Github actions node version

* Chore: Refactor observer interface

* Chore: Refactor node/edge constructor settings

* Chore: Refactor node/edge function grouping

* Chore: Refactor node/edge function grouping

* Fix: Listeners behaviour

* Chore: Refactor property copying

* Chore: Refactor subject implementation

* Fix: Set position behaviour on node drag

* Chore: Upgrade node version

* Chore: Refactor function type check

* Fix: Remove listener behaviour

* Chore: Refactor util naming

* Chore: Remove unused type assertion

* Chore: Refactor position setter options

* Chore: Refactor property patch function

* Fix: Set map node position behaviour

* Chore: Refactor simulator data patching

* Chore: Change observers to callbacks

* New: Add state setters with options (#95)

* New: Add state setters with options

* Chore: Remove leftover comments

* Chore: Refactor state setter logic

* Chore: Refactor state types

* Fix: Rename merged function usage

* Fix: Merged variable naming

* Chore: Fix tests

---------

Co-authored-by: dlozic <davidlozic@gmail.com>
Co-authored-by: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com>
Co-authored-by: AlexIchenskiy <aichenskiy@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants